mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-16 12:55:19 +03:00
Merge pull request #11597 from SteveCEvans/check_eeprom_write
This commit is contained in:
commit
a615cee171
6 changed files with 85 additions and 31 deletions
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "common/crc.h"
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include "streambuf.h"
|
#include "streambuf.h"
|
||||||
|
@ -114,3 +116,17 @@ void crc8_xor_sbuf_append(sbuf_t *dst, uint8_t *start)
|
||||||
sbufWriteU8(dst, crc);
|
sbufWriteU8(dst, crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fowler–Noll–Vo hash function; see https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
|
||||||
|
uint32_t fnv_update(uint32_t hash, const void *data, uint32_t length)
|
||||||
|
{
|
||||||
|
const uint8_t *p = (const uint8_t *)data;
|
||||||
|
const uint8_t *pend = p + length;
|
||||||
|
|
||||||
|
for (; p != pend; p++) {
|
||||||
|
hash *= FNV_PRIME;
|
||||||
|
hash ^= *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,3 +38,8 @@ void crc8_sbuf_append(struct sbuf_s *dst, uint8_t *start, uint8_t poly);
|
||||||
|
|
||||||
uint8_t crc8_xor_update(uint8_t crc, const void *data, uint32_t length);
|
uint8_t crc8_xor_update(uint8_t crc, const void *data, uint32_t length);
|
||||||
void crc8_xor_sbuf_append(struct sbuf_s *dst, uint8_t *start);
|
void crc8_xor_sbuf_append(struct sbuf_s *dst, uint8_t *start);
|
||||||
|
|
||||||
|
#define FNV_PRIME 16777619
|
||||||
|
#define FNV_OFFSET_BASIS 2166136261
|
||||||
|
|
||||||
|
uint32_t fnv_update(uint32_t hash, const void *data, uint32_t length);
|
||||||
|
|
|
@ -388,6 +388,7 @@ bool loadEEPROM(void)
|
||||||
|
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
*reg->fnv_hash = fnv_update(FNV_OFFSET_BASIS, reg->address, pgSize(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
@ -395,16 +396,26 @@ bool loadEEPROM(void)
|
||||||
|
|
||||||
static bool writeSettingsToEEPROM(void)
|
static bool writeSettingsToEEPROM(void)
|
||||||
{
|
{
|
||||||
config_streamer_t streamer;
|
bool dirtyConfig = !isEEPROMVersionValid() || !isEEPROMStructureValid();
|
||||||
config_streamer_init(&streamer);
|
|
||||||
|
|
||||||
config_streamer_start(&streamer, (uintptr_t)&__config_start, &__config_end - &__config_start);
|
|
||||||
|
|
||||||
configHeader_t header = {
|
configHeader_t header = {
|
||||||
.eepromConfigVersion = EEPROM_CONF_VERSION,
|
.eepromConfigVersion = EEPROM_CONF_VERSION,
|
||||||
.magic_be = 0xBE,
|
.magic_be = 0xBE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PG_FOREACH(reg) {
|
||||||
|
if (*reg->fnv_hash != fnv_update(FNV_OFFSET_BASIS, reg->address, pgSize(reg))) {
|
||||||
|
dirtyConfig = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only write the config if it has changed
|
||||||
|
if (dirtyConfig) {
|
||||||
|
config_streamer_t streamer;
|
||||||
|
config_streamer_init(&streamer);
|
||||||
|
|
||||||
|
config_streamer_start(&streamer, (uintptr_t)&__config_start, &__config_end - &__config_start);
|
||||||
|
|
||||||
config_streamer_write(&streamer, (uint8_t *)&header, sizeof(header));
|
config_streamer_write(&streamer, (uint8_t *)&header, sizeof(header));
|
||||||
uint16_t crc = CRC_START_VALUE;
|
uint16_t crc = CRC_START_VALUE;
|
||||||
crc = crc16_ccitt_update(crc, (uint8_t *)&header, sizeof(header));
|
crc = crc16_ccitt_update(crc, (uint8_t *)&header, sizeof(header));
|
||||||
|
@ -414,9 +425,10 @@ static bool writeSettingsToEEPROM(void)
|
||||||
.size = sizeof(configRecord_t) + regSize,
|
.size = sizeof(configRecord_t) + regSize,
|
||||||
.pgn = pgN(reg),
|
.pgn = pgN(reg),
|
||||||
.version = pgVersion(reg),
|
.version = pgVersion(reg),
|
||||||
.flags = 0
|
.flags = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
record.flags |= CR_CLASSICATION_SYSTEM;
|
record.flags |= CR_CLASSICATION_SYSTEM;
|
||||||
config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
|
config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
|
||||||
crc = crc16_ccitt_update(crc, (uint8_t *)&record, sizeof(record));
|
crc = crc16_ccitt_update(crc, (uint8_t *)&record, sizeof(record));
|
||||||
|
@ -437,9 +449,10 @@ static bool writeSettingsToEEPROM(void)
|
||||||
|
|
||||||
config_streamer_flush(&streamer);
|
config_streamer_flush(&streamer);
|
||||||
|
|
||||||
const bool success = config_streamer_finish(&streamer) == 0;
|
return (config_streamer_finish(&streamer) == 0);
|
||||||
|
} else {
|
||||||
return success;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeConfigToEEPROM(void)
|
void writeConfigToEEPROM(void)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "common/crc.h"
|
||||||
#include "common/maths.h"
|
#include "common/maths.h"
|
||||||
|
|
||||||
#include "pg.h"
|
#include "pg.h"
|
||||||
|
@ -80,6 +81,8 @@ bool pgLoad(const pgRegistry_t* reg, const void *from, int size, int version)
|
||||||
const int take = MIN(size, pgSize(reg));
|
const int take = MIN(size, pgSize(reg));
|
||||||
memcpy(pgOffset(reg), from, take);
|
memcpy(pgOffset(reg), from, take);
|
||||||
|
|
||||||
|
*reg->fnv_hash = fnv_update(FNV_OFFSET_BASIS, from, take);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ typedef struct pgRegistry_s {
|
||||||
void *ptr; // Pointer to init template
|
void *ptr; // Pointer to init template
|
||||||
pgResetFunc *fn; // Popinter to pgResetFunc
|
pgResetFunc *fn; // Popinter to pgResetFunc
|
||||||
} reset;
|
} reset;
|
||||||
|
uint32_t *fnv_hash; // Used to detect if config has changed prior to write
|
||||||
} pgRegistry_t;
|
} pgRegistry_t;
|
||||||
|
|
||||||
static inline uint16_t pgN(const pgRegistry_t* reg) {return reg->pgn & PGR_PGN_MASK;}
|
static inline uint16_t pgN(const pgRegistry_t* reg) {return reg->pgn & PGR_PGN_MASK;}
|
||||||
|
@ -118,6 +119,7 @@ extern const uint8_t __pg_resetdata_end[];
|
||||||
#define PG_REGISTER_I(_type, _name, _pgn, _version, _reset) \
|
#define PG_REGISTER_I(_type, _name, _pgn, _version, _reset) \
|
||||||
_type _name ## _System; \
|
_type _name ## _System; \
|
||||||
_type _name ## _Copy; \
|
_type _name ## _Copy; \
|
||||||
|
uint32_t _name ## _fnv_hash; \
|
||||||
/* Force external linkage for g++. Catch multi registration */ \
|
/* Force external linkage for g++. Catch multi registration */ \
|
||||||
extern const pgRegistry_t _name ## _Registry; \
|
extern const pgRegistry_t _name ## _Registry; \
|
||||||
const pgRegistry_t _name ##_Registry PG_REGISTER_ATTRIBUTES = { \
|
const pgRegistry_t _name ##_Registry PG_REGISTER_ATTRIBUTES = { \
|
||||||
|
@ -125,6 +127,7 @@ extern const uint8_t __pg_resetdata_end[];
|
||||||
.length = 1, \
|
.length = 1, \
|
||||||
.size = sizeof(_type) | PGR_SIZE_SYSTEM_FLAG, \
|
.size = sizeof(_type) | PGR_SIZE_SYSTEM_FLAG, \
|
||||||
.address = (uint8_t*)&_name ## _System, \
|
.address = (uint8_t*)&_name ## _System, \
|
||||||
|
.fnv_hash = &_name ## _fnv_hash, \
|
||||||
.copy = (uint8_t*)&_name ## _Copy, \
|
.copy = (uint8_t*)&_name ## _Copy, \
|
||||||
.ptr = 0, \
|
.ptr = 0, \
|
||||||
_reset, \
|
_reset, \
|
||||||
|
@ -149,12 +152,14 @@ extern const uint8_t __pg_resetdata_end[];
|
||||||
#define PG_REGISTER_ARRAY_I(_type, _length, _name, _pgn, _version, _reset) \
|
#define PG_REGISTER_ARRAY_I(_type, _length, _name, _pgn, _version, _reset) \
|
||||||
_type _name ## _SystemArray[_length]; \
|
_type _name ## _SystemArray[_length]; \
|
||||||
_type _name ## _CopyArray[_length]; \
|
_type _name ## _CopyArray[_length]; \
|
||||||
|
uint32_t _name ## _fnv_hash; \
|
||||||
extern const pgRegistry_t _name ##_Registry; \
|
extern const pgRegistry_t _name ##_Registry; \
|
||||||
const pgRegistry_t _name ## _Registry PG_REGISTER_ATTRIBUTES = { \
|
const pgRegistry_t _name ## _Registry PG_REGISTER_ATTRIBUTES = { \
|
||||||
.pgn = _pgn | (_version << 12), \
|
.pgn = _pgn | (_version << 12), \
|
||||||
.length = _length, \
|
.length = _length, \
|
||||||
.size = (sizeof(_type) * _length) | PGR_SIZE_SYSTEM_FLAG, \
|
.size = (sizeof(_type) * _length) | PGR_SIZE_SYSTEM_FLAG, \
|
||||||
.address = (uint8_t*)&_name ## _SystemArray, \
|
.address = (uint8_t*)&_name ## _SystemArray, \
|
||||||
|
.fnv_hash = &_name ## _fnv_hash, \
|
||||||
.copy = (uint8_t*)&_name ## _CopyArray, \
|
.copy = (uint8_t*)&_name ## _CopyArray, \
|
||||||
.ptr = 0, \
|
.ptr = 0, \
|
||||||
_reset, \
|
_reset, \
|
||||||
|
|
|
@ -106,7 +106,9 @@ blackbox_encoding_unittest_SRC := \
|
||||||
|
|
||||||
cli_unittest_SRC := \
|
cli_unittest_SRC := \
|
||||||
$(USER_DIR)/cli/cli.c \
|
$(USER_DIR)/cli/cli.c \
|
||||||
|
$(USER_DIR)/common/crc.c \
|
||||||
$(USER_DIR)/common/printf.c \
|
$(USER_DIR)/common/printf.c \
|
||||||
|
$(USER_DIR)/common/streambuf.c \
|
||||||
$(USER_DIR)/config/feature.c \
|
$(USER_DIR)/config/feature.c \
|
||||||
$(USER_DIR)/pg/pg.c \
|
$(USER_DIR)/pg/pg.c \
|
||||||
$(USER_DIR)/common/typeconversion.c
|
$(USER_DIR)/common/typeconversion.c
|
||||||
|
@ -227,6 +229,8 @@ link_quality_unittest_DEFINES := \
|
||||||
USE_RX_LINK_QUALITY_INFO=
|
USE_RX_LINK_QUALITY_INFO=
|
||||||
|
|
||||||
pg_unittest_SRC := \
|
pg_unittest_SRC := \
|
||||||
|
$(USER_DIR)/common/crc.c \
|
||||||
|
$(USER_DIR)/common/streambuf.c \
|
||||||
$(USER_DIR)/pg/pg.c
|
$(USER_DIR)/pg/pg.c
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,7 +238,9 @@ rc_controls_unittest_SRC := \
|
||||||
$(USER_DIR)/fc/rc_controls.c \
|
$(USER_DIR)/fc/rc_controls.c \
|
||||||
$(USER_DIR)/pg/pg.c \
|
$(USER_DIR)/pg/pg.c \
|
||||||
$(USER_DIR)/common/bitarray.c \
|
$(USER_DIR)/common/bitarray.c \
|
||||||
|
$(USER_DIR)/common/crc.c \
|
||||||
$(USER_DIR)/common/maths.c \
|
$(USER_DIR)/common/maths.c \
|
||||||
|
$(USER_DIR)/common/streambuf.c \
|
||||||
$(USER_DIR)/fc/rc_adjustments.c \
|
$(USER_DIR)/fc/rc_adjustments.c \
|
||||||
$(USER_DIR)/fc/rc_modes.c
|
$(USER_DIR)/fc/rc_modes.c
|
||||||
|
|
||||||
|
@ -254,7 +260,9 @@ rx_ibus_unittest_SRC := \
|
||||||
|
|
||||||
rx_ranges_unittest_SRC := \
|
rx_ranges_unittest_SRC := \
|
||||||
$(USER_DIR)/common/bitarray.c \
|
$(USER_DIR)/common/bitarray.c \
|
||||||
|
$(USER_DIR)/common/crc.c \
|
||||||
$(USER_DIR)/common/maths.c \
|
$(USER_DIR)/common/maths.c \
|
||||||
|
$(USER_DIR)/common/streambuf.c \
|
||||||
$(USER_DIR)/fc/rc_modes.c \
|
$(USER_DIR)/fc/rc_modes.c \
|
||||||
$(USER_DIR)/rx/rx.c \
|
$(USER_DIR)/rx/rx.c \
|
||||||
$(USER_DIR)/pg/pg.c \
|
$(USER_DIR)/pg/pg.c \
|
||||||
|
@ -287,7 +295,9 @@ sensor_gyro_unittest_SRC := \
|
||||||
$(USER_DIR)/sensors/gyro_init.c \
|
$(USER_DIR)/sensors/gyro_init.c \
|
||||||
$(USER_DIR)/sensors/boardalignment.c \
|
$(USER_DIR)/sensors/boardalignment.c \
|
||||||
$(USER_DIR)/common/filter.c \
|
$(USER_DIR)/common/filter.c \
|
||||||
|
$(USER_DIR)/common/crc.c \
|
||||||
$(USER_DIR)/common/maths.c \
|
$(USER_DIR)/common/maths.c \
|
||||||
|
$(USER_DIR)/common/streambuf.c \
|
||||||
$(USER_DIR)/common/sensor_alignment.c \
|
$(USER_DIR)/common/sensor_alignment.c \
|
||||||
$(USER_DIR)/drivers/accgyro/accgyro_fake.c \
|
$(USER_DIR)/drivers/accgyro/accgyro_fake.c \
|
||||||
$(USER_DIR)/drivers/accgyro/gyro_sync.c \
|
$(USER_DIR)/drivers/accgyro/gyro_sync.c \
|
||||||
|
@ -378,8 +388,10 @@ rcdevice_unittest_SRC := \
|
||||||
$(USER_DIR)/pg/pg.c \
|
$(USER_DIR)/pg/pg.c \
|
||||||
|
|
||||||
pid_unittest_SRC := \
|
pid_unittest_SRC := \
|
||||||
|
$(USER_DIR)/common/crc.c \
|
||||||
$(USER_DIR)/common/filter.c \
|
$(USER_DIR)/common/filter.c \
|
||||||
$(USER_DIR)/common/maths.c \
|
$(USER_DIR)/common/maths.c \
|
||||||
|
$(USER_DIR)/common/streambuf.c \
|
||||||
$(USER_DIR)/drivers/accgyro/gyro_sync.c \
|
$(USER_DIR)/drivers/accgyro/gyro_sync.c \
|
||||||
$(USER_DIR)/fc/controlrate_profile.c \
|
$(USER_DIR)/fc/controlrate_profile.c \
|
||||||
$(USER_DIR)/fc/runtime_config.c \
|
$(USER_DIR)/fc/runtime_config.c \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue