mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-19 09:54:15 +01:00
Merge remote-tracking branch 'origin/amorale/OP-954_logfs_settings_in_internal_flash' into next
Conflicts: flight/pios/common/pios_flashfs_logfs.c
This commit is contained in:
commit
c1f767b12d
@ -471,38 +471,41 @@ static void ProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rxbyt
|
||||
switch (obj_per.Operation) {
|
||||
case OBJECTPERSISTENCE_OPERATION_LOAD:
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_FLASH_EEPROM)
|
||||
#if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
|
||||
// Load the settings.
|
||||
OPLinkSettingsData oplinkSettings;
|
||||
if (PIOS_EEPROM_Load((uint8_t*)&oplinkSettings, sizeof(OPLinkSettingsData)) == 0)
|
||||
OPLinkSettingsSet(&oplinkSettings);
|
||||
else
|
||||
void *obj = UAVObjGetByID(obj_per.ObjectID);
|
||||
if (obj == 0) {
|
||||
success = false;
|
||||
} else {
|
||||
// Load selected instance
|
||||
success = (UAVObjLoad(obj, obj_per.InstanceID) == 0);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case OBJECTPERSISTENCE_OPERATION_SAVE:
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_FLASH_EEPROM)
|
||||
// Save the settings.
|
||||
OPLinkSettingsData oplinkSettings;
|
||||
OPLinkSettingsGet(&oplinkSettings);
|
||||
int32_t ret = PIOS_EEPROM_Save((uint8_t*)&oplinkSettings, sizeof(OPLinkSettingsData));
|
||||
if (ret != 0)
|
||||
#if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
|
||||
void *obj = UAVObjGetByID(obj_per.ObjectID);
|
||||
if (obj == 0) {
|
||||
success = false;
|
||||
} else {
|
||||
// Save selected instance
|
||||
success = UAVObjSave(obj, obj_per.InstanceID) == 0;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case OBJECTPERSISTENCE_OPERATION_DELETE:
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_FLASH_EEPROM)
|
||||
// Erase the settings.
|
||||
OPLinkSettingsData oplinkSettings;
|
||||
uint8_t *ptr = (uint8_t*)&oplinkSettings;
|
||||
memset(ptr, 0, sizeof(OPLinkSettingsData));
|
||||
int32_t ret = PIOS_EEPROM_Save(ptr, sizeof(OPLinkSettingsData));
|
||||
if (ret != 0)
|
||||
#if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
|
||||
void *obj = UAVObjGetByID(obj_per.ObjectID);
|
||||
if (obj == 0) {
|
||||
success = false;
|
||||
} else {
|
||||
// Save selected instance
|
||||
success = UAVObjDelete(obj, obj_per.InstanceID) == 0;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ static void objectUpdatedCb(UAVObjEvent * ev)
|
||||
retval = UAVObjDeleteMetaobjects();
|
||||
}
|
||||
} else if (objper.Operation == OBJECTPERSISTENCE_OPERATION_FULLERASE) {
|
||||
#if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS)
|
||||
#if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
|
||||
retval = PIOS_FLASHFS_Format(0);
|
||||
#else
|
||||
retval = -1;
|
||||
|
@ -39,7 +39,12 @@
|
||||
* Filesystem state data tracked in RAM
|
||||
*/
|
||||
|
||||
enum pios_flashfs_logfs_dev_magic {
|
||||
PIOS_FLASHFS_LOGFS_DEV_MAGIC = 0x94938201,
|
||||
};
|
||||
|
||||
struct logfs_state {
|
||||
enum pios_flashfs_logfs_dev_magic magic;
|
||||
const struct flashfs_logfs_cfg * cfg;
|
||||
bool mounted;
|
||||
uint8_t active_arena_id;
|
||||
@ -56,8 +61,6 @@ struct logfs_state {
|
||||
uintptr_t flash_id;
|
||||
};
|
||||
|
||||
static struct logfs_state logfs;
|
||||
|
||||
/*
|
||||
* Internal Utility functions
|
||||
*/
|
||||
@ -66,14 +69,14 @@ static struct logfs_state logfs;
|
||||
* @brief Return the offset in flash of a particular slot within an arena
|
||||
* @return address of the requested slot
|
||||
*/
|
||||
static uintptr_t logfs_get_addr(uint8_t arena_id, uint16_t slot_id)
|
||||
static uintptr_t logfs_get_addr(const struct logfs_state * logfs, uint8_t arena_id, uint16_t slot_id)
|
||||
{
|
||||
PIOS_Assert(arena_id < (logfs.cfg->total_fs_size / logfs.cfg->arena_size));
|
||||
PIOS_Assert(slot_id < (logfs.cfg->arena_size / logfs.cfg->slot_size));
|
||||
PIOS_Assert(arena_id < (logfs->cfg->total_fs_size / logfs->cfg->arena_size));
|
||||
PIOS_Assert(slot_id < (logfs->cfg->arena_size / logfs->cfg->slot_size));
|
||||
|
||||
return (logfs.cfg->start_offset +
|
||||
(arena_id * logfs.cfg->arena_size) +
|
||||
(slot_id * logfs.cfg->slot_size));
|
||||
return (logfs->cfg->start_offset +
|
||||
(arena_id * logfs->cfg->arena_size) +
|
||||
(slot_id * logfs->cfg->slot_size));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -112,27 +115,27 @@ struct arena_header {
|
||||
* @return 0 if success, < 0 on failure
|
||||
* @note Must be called while holding the flash transaction lock
|
||||
*/
|
||||
static int32_t logfs_erase_arena(uint8_t arena_id)
|
||||
static int32_t logfs_erase_arena(const struct logfs_state * logfs, uint8_t arena_id)
|
||||
{
|
||||
uintptr_t arena_addr = logfs_get_addr (arena_id, 0);
|
||||
uintptr_t arena_addr = logfs_get_addr (logfs, arena_id, 0);
|
||||
|
||||
/* Erase all of the sectors in the arena */
|
||||
for (uint8_t sector_id = 0;
|
||||
sector_id < (logfs.cfg->arena_size / logfs.cfg->sector_size);
|
||||
sector_id < (logfs->cfg->arena_size / logfs->cfg->sector_size);
|
||||
sector_id++) {
|
||||
if (logfs.driver->erase_sector(logfs.flash_id,
|
||||
arena_addr + (sector_id * logfs.cfg->sector_size))) {
|
||||
if (logfs->driver->erase_sector(logfs->flash_id,
|
||||
arena_addr + (sector_id * logfs->cfg->sector_size))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark this arena as fully erased */
|
||||
struct arena_header arena_hdr = {
|
||||
.magic = logfs.cfg->fs_magic,
|
||||
.magic = logfs->cfg->fs_magic,
|
||||
.state = ARENA_STATE_ERASED,
|
||||
};
|
||||
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
@ -149,13 +152,13 @@ static int32_t logfs_erase_arena(uint8_t arena_id)
|
||||
* @note Arena must have been previously erased before calling this
|
||||
* @note Must be called while holding the flash transaction lock
|
||||
*/
|
||||
static int32_t logfs_reserve_arena (uint8_t arena_id)
|
||||
static int32_t logfs_reserve_arena (const struct logfs_state * logfs, uint8_t arena_id)
|
||||
{
|
||||
uintptr_t arena_addr = logfs_get_addr (arena_id, 0);
|
||||
uintptr_t arena_addr = logfs_get_addr (logfs, arena_id, 0);
|
||||
|
||||
/* Read in the current arena header */
|
||||
struct arena_header arena_hdr;
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
@ -170,7 +173,7 @@ static int32_t logfs_reserve_arena (uint8_t arena_id)
|
||||
arena_hdr.state = ARENA_STATE_RESERVED;
|
||||
|
||||
/* Write the arena header back to flash */
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
@ -186,9 +189,9 @@ static int32_t logfs_reserve_arena (uint8_t arena_id)
|
||||
* @return 0 if success, < 0 on failure
|
||||
* @note Must be called while holding the flash transaction lock
|
||||
*/
|
||||
static int32_t logfs_erase_all_arenas()
|
||||
static int32_t logfs_erase_all_arenas(const struct logfs_state * logfs)
|
||||
{
|
||||
uint16_t num_arenas = logfs.cfg->total_fs_size / logfs.cfg->arena_size;
|
||||
uint16_t num_arenas = logfs->cfg->total_fs_size / logfs->cfg->arena_size;
|
||||
|
||||
for (uint16_t arena = 0; arena < num_arenas; arena++) {
|
||||
#ifdef PIOS_LED_HEARTBEAT
|
||||
@ -197,7 +200,7 @@ static int32_t logfs_erase_all_arenas()
|
||||
#ifdef PIOS_INCLUDE_WDG
|
||||
PIOS_WDG_Clear();
|
||||
#endif
|
||||
if (logfs_erase_arena(arena) != 0)
|
||||
if (logfs_erase_arena(logfs, arena) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -210,13 +213,13 @@ static int32_t logfs_erase_all_arenas()
|
||||
* @note Arena must have been previously erased or reserved before calling this
|
||||
* @note Must be called while holding the flash transaction lock
|
||||
*/
|
||||
static int32_t logfs_activate_arena(uint8_t arena_id)
|
||||
static int32_t logfs_activate_arena(const struct logfs_state * logfs, uint8_t arena_id)
|
||||
{
|
||||
uintptr_t arena_addr = logfs_get_addr(arena_id, 0);
|
||||
uintptr_t arena_addr = logfs_get_addr(logfs, arena_id, 0);
|
||||
|
||||
/* Make sure this arena has been previously erased */
|
||||
struct arena_header arena_hdr;
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof (arena_hdr)) != 0) {
|
||||
@ -231,7 +234,7 @@ static int32_t logfs_activate_arena(uint8_t arena_id)
|
||||
|
||||
/* Mark this arena as active */
|
||||
arena_hdr.state = ARENA_STATE_ACTIVE;
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
@ -248,16 +251,16 @@ static int32_t logfs_activate_arena(uint8_t arena_id)
|
||||
* @note Arena must have been previously active before calling this
|
||||
* @note Must be called while holding the flash transaction lock
|
||||
*/
|
||||
static int32_t logfs_obsolete_arena(uint8_t arena_id)
|
||||
static int32_t logfs_obsolete_arena(const struct logfs_state * logfs, uint8_t arena_id)
|
||||
{
|
||||
uintptr_t arena_addr = logfs_get_addr (arena_id, 0);
|
||||
uintptr_t arena_addr = logfs_get_addr (logfs, arena_id, 0);
|
||||
|
||||
/* We shouldn't be retiring the currently active arena */
|
||||
PIOS_Assert(!logfs.mounted);
|
||||
PIOS_Assert(!logfs->mounted);
|
||||
|
||||
/* Make sure this arena was previously active */
|
||||
struct arena_header arena_hdr;
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof (arena_hdr)) != 0) {
|
||||
@ -272,7 +275,7 @@ static int32_t logfs_obsolete_arena(uint8_t arena_id)
|
||||
|
||||
/* Mark this arena as obsolete */
|
||||
arena_hdr.state = ARENA_STATE_OBSOLETE;
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
@ -290,23 +293,23 @@ static int32_t logfs_obsolete_arena(uint8_t arena_id)
|
||||
* @return -2 if failed to read arena header
|
||||
* @note Must be called while holding the flash transaction lock
|
||||
*/
|
||||
static int32_t logfs_find_active_arena()
|
||||
static int32_t logfs_find_active_arena(const struct logfs_state * logfs)
|
||||
{
|
||||
/* Search for the lowest numbered active arena */
|
||||
for (uint8_t arena_id = 0;
|
||||
arena_id < logfs.cfg->total_fs_size / logfs.cfg->arena_size;
|
||||
arena_id < logfs->cfg->total_fs_size / logfs->cfg->arena_size;
|
||||
arena_id++) {
|
||||
uintptr_t arena_addr = logfs_get_addr (arena_id, 0);
|
||||
uintptr_t arena_addr = logfs_get_addr (logfs, arena_id, 0);
|
||||
/* Load the arena header */
|
||||
struct arena_header arena_hdr;
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof (arena_hdr)) != 0) {
|
||||
return -2;
|
||||
}
|
||||
if ((arena_hdr.state == ARENA_STATE_ACTIVE) &&
|
||||
(arena_hdr.magic == logfs.cfg->fs_magic)) {
|
||||
(arena_hdr.magic == logfs->cfg->fs_magic)) {
|
||||
/* This is the first active arena */
|
||||
return arena_id;
|
||||
}
|
||||
@ -349,7 +352,7 @@ struct slot_header {
|
||||
} __attribute__((packed));
|
||||
|
||||
/* NOTE: Must be called while holding the flash transaction lock */
|
||||
static int32_t logfs_raw_copy_bytes (uintptr_t src_addr, uint16_t src_size, uintptr_t dst_addr)
|
||||
static int32_t logfs_raw_copy_bytes (const struct logfs_state * logfs, uintptr_t src_addr, uint16_t src_size, uintptr_t dst_addr)
|
||||
{
|
||||
#define RAW_COPY_BLOCK_SIZE 16
|
||||
uint8_t data_block[RAW_COPY_BLOCK_SIZE];
|
||||
@ -365,7 +368,7 @@ static int32_t logfs_raw_copy_bytes (uintptr_t src_addr, uint16_t src_size, uint
|
||||
}
|
||||
|
||||
/* Read a block of data from source */
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
src_addr,
|
||||
data_block,
|
||||
blk_size) != 0) {
|
||||
@ -374,7 +377,7 @@ static int32_t logfs_raw_copy_bytes (uintptr_t src_addr, uint16_t src_size, uint
|
||||
}
|
||||
|
||||
/* Write a block of data to destination */
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
dst_addr,
|
||||
data_block,
|
||||
blk_size) != 0) {
|
||||
@ -396,9 +399,9 @@ static int32_t logfs_raw_copy_bytes (uintptr_t src_addr, uint16_t src_size, uint
|
||||
* true = all slots in the arena are in the ACTIVE state (ie. garbage collection won't free anything)
|
||||
* false = some slots in the arena are either currently free or could be free'd by garbage collection
|
||||
*/
|
||||
static bool logfs_fs_is_full(void)
|
||||
static bool logfs_fs_is_full(const struct logfs_state * logfs)
|
||||
{
|
||||
return (logfs.num_active_slots == (logfs.cfg->arena_size / logfs.cfg->slot_size) - 1);
|
||||
return (logfs->num_active_slots == (logfs->cfg->arena_size / logfs->cfg->slot_size) - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -406,37 +409,37 @@ static bool logfs_fs_is_full(void)
|
||||
* true = there are no unwritten slots left in the log (garbage collection may or may not help)
|
||||
* false = there are still some entirely unused slots left in the log
|
||||
*/
|
||||
static bool logfs_log_is_full(void)
|
||||
static bool logfs_log_is_full(const struct logfs_state * logfs)
|
||||
{
|
||||
return (logfs.num_free_slots == 0);
|
||||
return (logfs->num_free_slots == 0);
|
||||
}
|
||||
|
||||
static int32_t logfs_unmount_log(void)
|
||||
static int32_t logfs_unmount_log(struct logfs_state * logfs)
|
||||
{
|
||||
PIOS_Assert (logfs.mounted);
|
||||
PIOS_Assert (logfs->mounted);
|
||||
|
||||
logfs.num_active_slots = 0;
|
||||
logfs.num_free_slots = 0;
|
||||
logfs.mounted = false;
|
||||
logfs->num_active_slots = 0;
|
||||
logfs->num_free_slots = 0;
|
||||
logfs->mounted = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t logfs_mount_log(uint8_t arena_id)
|
||||
static int32_t logfs_mount_log(struct logfs_state * logfs, uint8_t arena_id)
|
||||
{
|
||||
PIOS_Assert (!logfs.mounted);
|
||||
PIOS_Assert (!logfs->mounted);
|
||||
|
||||
logfs.num_active_slots = 0;
|
||||
logfs.num_free_slots = 0;
|
||||
logfs.active_arena_id = arena_id;
|
||||
logfs->num_active_slots = 0;
|
||||
logfs->num_free_slots = 0;
|
||||
logfs->active_arena_id = arena_id;
|
||||
|
||||
/* Scan the log to find out how full it is */
|
||||
for (uint16_t slot_id = 1;
|
||||
slot_id < (logfs.cfg->arena_size / logfs.cfg->slot_size);
|
||||
slot_id < (logfs->cfg->arena_size / logfs->cfg->slot_size);
|
||||
slot_id++) {
|
||||
struct slot_header slot_hdr;
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id);
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs, logfs->active_arena_id, slot_id);
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof (slot_hdr)) != 0) {
|
||||
@ -448,14 +451,14 @@ static int32_t logfs_mount_log(uint8_t arena_id)
|
||||
* end of the arena.
|
||||
*/
|
||||
PIOS_Assert (slot_hdr.state == SLOT_STATE_EMPTY ||
|
||||
logfs.num_free_slots == 0);
|
||||
logfs->num_free_slots == 0);
|
||||
|
||||
switch (slot_hdr.state) {
|
||||
case SLOT_STATE_EMPTY:
|
||||
logfs.num_free_slots++;
|
||||
logfs->num_free_slots++;
|
||||
break;
|
||||
case SLOT_STATE_ACTIVE:
|
||||
logfs.num_active_slots++;
|
||||
logfs->num_active_slots++;
|
||||
break;
|
||||
case SLOT_STATE_RESERVED:
|
||||
case SLOT_STATE_OBSOLETE:
|
||||
@ -464,12 +467,59 @@ static int32_t logfs_mount_log(uint8_t arena_id)
|
||||
}
|
||||
|
||||
/* Scan is complete, mark the arena mounted */
|
||||
logfs.active_arena_id = arena_id;
|
||||
logfs.mounted = true;
|
||||
logfs->active_arena_id = arena_id;
|
||||
logfs->mounted = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool PIOS_FLASHFS_Logfs_validate(const struct logfs_state * logfs)
|
||||
{
|
||||
return (logfs && (logfs->magic == PIOS_FLASHFS_LOGFS_DEV_MAGIC));
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
static struct logfs_state * PIOS_FLASHFS_Logfs_alloc(void)
|
||||
{
|
||||
struct logfs_state * logfs;
|
||||
|
||||
logfs = (struct logfs_state *)pvPortMalloc(sizeof(*logfs));
|
||||
if (!logfs) return (NULL);
|
||||
|
||||
logfs->magic = PIOS_FLASHFS_LOGFS_DEV_MAGIC;
|
||||
return(logfs);
|
||||
}
|
||||
static void PIOS_FLASHFS_Logfs_free(struct logfs_state * logfs)
|
||||
{
|
||||
/* Invalidate the magic */
|
||||
logfs->magic = ~PIOS_FLASHFS_LOGFS_DEV_MAGIC;
|
||||
vPortFree(logfs);
|
||||
}
|
||||
#else
|
||||
static struct logfs_state pios_flashfs_logfs_devs[PIOS_FLASHFS_LOGFS_MAX_DEVS];
|
||||
static uint8_t pios_flashfs_logfs_num_devs;
|
||||
static struct logfs_state * PIOS_FLASHFS_Logfs_alloc(void)
|
||||
{
|
||||
struct logfs_state * logfs;
|
||||
|
||||
if (pios_flashfs_logfs_num_devs >= PIOS_FLASHFS_LOGFS_MAX_DEVS) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
logfs = &pios_flashfs_logfs_devs[pios_flashfs_logfs_num_devs++];
|
||||
logfs->magic = PIOS_FLASHFS_LOGFS_DEV_MAGIC;
|
||||
|
||||
return (logfs);
|
||||
}
|
||||
static void PIOS_FLASHFS_Logfs_free(struct logfs_state * logfs)
|
||||
{
|
||||
/* Invalidate the magic */
|
||||
logfs->magic = ~PIOS_FLASHFS_LOGFS_DEV_MAGIC;
|
||||
|
||||
/* Can't free the resources with this simple allocator */
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the flash object setting FS
|
||||
* @return 0 if success, -1 if failure
|
||||
@ -490,15 +540,23 @@ int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cf
|
||||
PIOS_Assert(driver->write_data);
|
||||
PIOS_Assert(driver->read_data);
|
||||
|
||||
/* Bind configuration parameters to this filesystem instance */
|
||||
logfs.cfg = cfg; /* filesystem configuration */
|
||||
logfs.driver = driver; /* lower-level flash driver */
|
||||
logfs.flash_id = flash_id; /* lower-level flash device id */
|
||||
logfs.mounted = false;
|
||||
|
||||
int8_t rc;
|
||||
|
||||
if (logfs.driver->start_transaction(logfs.flash_id) != 0) {
|
||||
struct logfs_state * logfs;
|
||||
|
||||
logfs = (struct logfs_state *) PIOS_FLASHFS_Logfs_alloc();
|
||||
if (!logfs) {
|
||||
rc = -1;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
/* Bind configuration parameters to this filesystem instance */
|
||||
logfs->cfg = cfg; /* filesystem configuration */
|
||||
logfs->driver = driver; /* lower-level flash driver */
|
||||
logfs->flash_id = flash_id; /* lower-level flash device id */
|
||||
logfs->mounted = false;
|
||||
|
||||
if (logfs->driver->start_transaction(logfs->flash_id) != 0) {
|
||||
rc = -1;
|
||||
goto out_exit;
|
||||
}
|
||||
@ -507,16 +565,16 @@ int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cf
|
||||
int32_t arena_id;
|
||||
for (uint8_t try = 0; !found && try < 2; try++) {
|
||||
/* Find the active arena */
|
||||
arena_id = logfs_find_active_arena();
|
||||
arena_id = logfs_find_active_arena(logfs);
|
||||
if (arena_id >= 0) {
|
||||
/* Found the active arena */
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
/* No active arena found, erase and activate arena 0 */
|
||||
if (logfs_erase_arena(0) != 0)
|
||||
if (logfs_erase_arena(logfs, 0) != 0)
|
||||
break;
|
||||
if (logfs_activate_arena(0) != 0)
|
||||
if (logfs_activate_arena(logfs, 0) != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -528,7 +586,7 @@ int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cf
|
||||
}
|
||||
|
||||
/* We've found an active arena, mount it */
|
||||
if (logfs_mount_log(arena_id) != 0) {
|
||||
if (logfs_mount_log(logfs, arena_id) != 0) {
|
||||
/* Failed to mount the log, something is broken */
|
||||
rc = -3;
|
||||
goto out_end_trans;
|
||||
@ -537,32 +595,50 @@ int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cf
|
||||
/* Log has been mounted */
|
||||
rc = 0;
|
||||
|
||||
*fs_id = (uintptr_t) &logfs;
|
||||
*fs_id = (uintptr_t) logfs;
|
||||
|
||||
out_end_trans:
|
||||
logfs.driver->end_transaction(logfs.flash_id);
|
||||
logfs->driver->end_transaction(logfs->flash_id);
|
||||
|
||||
out_exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t PIOS_FLASHFS_Logfs_Destroy(uintptr_t fs_id)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
struct logfs_state * logfs = (struct logfs_state *)fs_id;
|
||||
|
||||
if (!PIOS_FLASHFS_Logfs_validate(logfs)) {
|
||||
rc = -1;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
PIOS_FLASHFS_Logfs_free(logfs);
|
||||
rc = 0;
|
||||
|
||||
out_exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* NOTE: Must be called while holding the flash transaction lock */
|
||||
static int32_t logfs_garbage_collect (void) {
|
||||
PIOS_Assert (logfs.mounted);
|
||||
static int32_t logfs_garbage_collect (struct logfs_state * logfs) {
|
||||
PIOS_Assert (logfs->mounted);
|
||||
|
||||
/* Source arena is the active arena */
|
||||
uint8_t src_arena_id = logfs.active_arena_id;
|
||||
uint8_t src_arena_id = logfs->active_arena_id;
|
||||
|
||||
/* Compute destination arena */
|
||||
uint8_t dst_arena_id = (logfs.active_arena_id + 1) % (logfs.cfg->total_fs_size / logfs.cfg->arena_size);
|
||||
uint8_t dst_arena_id = (logfs->active_arena_id + 1) % (logfs->cfg->total_fs_size / logfs->cfg->arena_size);
|
||||
|
||||
/* Erase destination arena */
|
||||
if (logfs_erase_arena (dst_arena_id) != 0) {
|
||||
if (logfs_erase_arena (logfs, dst_arena_id) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Reserve the destination arena so we can start filling it */
|
||||
if (logfs_reserve_arena (dst_arena_id) != 0) {
|
||||
if (logfs_reserve_arena (logfs, dst_arena_id) != 0) {
|
||||
/* Unable to reserve the arena */
|
||||
return -2;
|
||||
}
|
||||
@ -570,11 +646,11 @@ static int32_t logfs_garbage_collect (void) {
|
||||
/* Copy active slots from active arena to destination arena */
|
||||
uint16_t dst_slot_id = 1;
|
||||
for (uint16_t src_slot_id = 1;
|
||||
src_slot_id < (logfs.cfg->arena_size / logfs.cfg->slot_size);
|
||||
src_slot_id < (logfs->cfg->arena_size / logfs->cfg->slot_size);
|
||||
src_slot_id++) {
|
||||
struct slot_header slot_hdr;
|
||||
uintptr_t src_addr = logfs_get_addr (src_arena_id, src_slot_id);
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
uintptr_t src_addr = logfs_get_addr (logfs, src_arena_id, src_slot_id);
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
src_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof (slot_hdr)) != 0) {
|
||||
@ -582,8 +658,9 @@ static int32_t logfs_garbage_collect (void) {
|
||||
}
|
||||
|
||||
if (slot_hdr.state == SLOT_STATE_ACTIVE) {
|
||||
uintptr_t dst_addr = logfs_get_addr (dst_arena_id, dst_slot_id);
|
||||
if (logfs_raw_copy_bytes(src_addr,
|
||||
uintptr_t dst_addr = logfs_get_addr (logfs, dst_arena_id, dst_slot_id);
|
||||
if (logfs_raw_copy_bytes(logfs,
|
||||
src_addr,
|
||||
sizeof(slot_hdr) + slot_hdr.obj_size,
|
||||
dst_addr) != 0) {
|
||||
/* Failed to copy all bytes */
|
||||
@ -597,22 +674,22 @@ static int32_t logfs_garbage_collect (void) {
|
||||
}
|
||||
|
||||
/* Activate the destination arena */
|
||||
if (logfs_activate_arena (dst_arena_id) != 0) {
|
||||
if (logfs_activate_arena (logfs, dst_arena_id) != 0) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* Unmount the source arena */
|
||||
if (logfs_unmount_log () != 0) {
|
||||
if (logfs_unmount_log (logfs) != 0) {
|
||||
return -6;
|
||||
}
|
||||
|
||||
/* Obsolete the source arena */
|
||||
if (logfs_obsolete_arena (src_arena_id) != 0) {
|
||||
if (logfs_obsolete_arena (logfs, src_arena_id) != 0) {
|
||||
return -7;
|
||||
}
|
||||
|
||||
/* Mount the new arena */
|
||||
if (logfs_mount_log (dst_arena_id) != 0) {
|
||||
if (logfs_mount_log (logfs, dst_arena_id) != 0) {
|
||||
return -8;
|
||||
}
|
||||
|
||||
@ -620,7 +697,7 @@ static int32_t logfs_garbage_collect (void) {
|
||||
}
|
||||
|
||||
/* NOTE: Must be called while holding the flash transaction lock */
|
||||
static int16_t logfs_object_find_next (struct slot_header * slot_hdr, uint16_t * curr_slot, uint32_t obj_id, uint16_t obj_inst_id)
|
||||
static int16_t logfs_object_find_next (const struct logfs_state * logfs, struct slot_header * slot_hdr, uint16_t * curr_slot, uint32_t obj_id, uint16_t obj_inst_id)
|
||||
{
|
||||
PIOS_Assert(slot_hdr);
|
||||
PIOS_Assert(curr_slot);
|
||||
@ -629,11 +706,11 @@ static int16_t logfs_object_find_next (struct slot_header * slot_hdr, uint16_t *
|
||||
if (*curr_slot == 0) *curr_slot = 1;
|
||||
|
||||
for (uint16_t slot_id = *curr_slot;
|
||||
slot_id < (logfs.cfg->arena_size / logfs.cfg->slot_size);
|
||||
slot_id < (logfs->cfg->arena_size / logfs->cfg->slot_size);
|
||||
slot_id++) {
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id);
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs, logfs->active_arena_id, slot_id);
|
||||
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof (*slot_hdr)) != 0) {
|
||||
@ -661,7 +738,7 @@ static int16_t logfs_object_find_next (struct slot_header * slot_hdr, uint16_t *
|
||||
|
||||
/* NOTE: Must be called while holding the flash transaction lock */
|
||||
/* OPTIMIZE: could trust that there is at most one active version of every object and terminate the search when we find one */
|
||||
static int8_t logfs_delete_object (uint32_t obj_id, uint16_t obj_inst_id)
|
||||
static int8_t logfs_delete_object (struct logfs_state * logfs, uint32_t obj_id, uint16_t obj_inst_id)
|
||||
{
|
||||
int8_t rc;
|
||||
|
||||
@ -669,13 +746,13 @@ static int8_t logfs_delete_object (uint32_t obj_id, uint16_t obj_inst_id)
|
||||
uint16_t curr_slot_id = 0;
|
||||
do {
|
||||
struct slot_header slot_hdr;
|
||||
switch (logfs_object_find_next (&slot_hdr, &curr_slot_id, obj_id, obj_inst_id)) {
|
||||
switch (logfs_object_find_next (logfs, &slot_hdr, &curr_slot_id, obj_id, obj_inst_id)) {
|
||||
case 0:
|
||||
/* Found a matching slot. Obsolete it. */
|
||||
slot_hdr.state = SLOT_STATE_OBSOLETE;
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, curr_slot_id);
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs, logfs->active_arena_id, curr_slot_id);
|
||||
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof(slot_hdr)) != 0) {
|
||||
@ -683,7 +760,7 @@ static int8_t logfs_delete_object (uint32_t obj_id, uint16_t obj_inst_id)
|
||||
goto out_exit;
|
||||
}
|
||||
/* Object has been successfully obsoleted and is no longer active */
|
||||
logfs.num_active_slots--;
|
||||
logfs->num_active_slots--;
|
||||
break;
|
||||
case -1:
|
||||
/* Search completed, object not found */
|
||||
@ -702,27 +779,27 @@ out_exit:
|
||||
}
|
||||
|
||||
/* NOTE: Must be called while holding the flash transaction lock */
|
||||
static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header * slot_hdr, uint32_t obj_id, uint16_t obj_inst_id, uint16_t obj_size)
|
||||
static int8_t logfs_reserve_free_slot (struct logfs_state * logfs, uint16_t * slot_id, struct slot_header * slot_hdr, uint32_t obj_id, uint16_t obj_inst_id, uint16_t obj_size)
|
||||
{
|
||||
PIOS_Assert(slot_id);
|
||||
PIOS_Assert(slot_hdr);
|
||||
|
||||
if (logfs.num_free_slots < 1) {
|
||||
if (logfs->num_free_slots < 1) {
|
||||
/* No free slots to allocate */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (obj_size > (logfs.cfg->slot_size - sizeof (slot_hdr))) {
|
||||
if (obj_size > (logfs->cfg->slot_size - sizeof (slot_hdr))) {
|
||||
/* This object is too big for the slot */
|
||||
return -2;
|
||||
}
|
||||
|
||||
uint16_t candidate_slot_id = (logfs.cfg->arena_size / logfs.cfg->slot_size) - logfs.num_free_slots;
|
||||
uint16_t candidate_slot_id = (logfs->cfg->arena_size / logfs->cfg->slot_size) - logfs->num_free_slots;
|
||||
PIOS_Assert(candidate_slot_id > 0);
|
||||
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, candidate_slot_id);
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs, logfs->active_arena_id, candidate_slot_id);
|
||||
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof (*slot_hdr)) != 0) {
|
||||
@ -742,7 +819,7 @@ static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header *
|
||||
slot_hdr->obj_inst_id = obj_inst_id;
|
||||
slot_hdr->obj_size = obj_size;
|
||||
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof(*slot_hdr)) != 0) {
|
||||
@ -751,33 +828,33 @@ static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header *
|
||||
}
|
||||
|
||||
/* FIXME: If the header write (above) failed, may have partially written data, thus corrupting that slot but we would have missed decrementing this counter */
|
||||
logfs.num_free_slots--;
|
||||
logfs->num_free_slots--;
|
||||
|
||||
*slot_id = candidate_slot_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NOTE: Must be called while holding the flash transaction lock */
|
||||
static int8_t logfs_append_to_log (uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size)
|
||||
static int8_t logfs_append_to_log (struct logfs_state * logfs, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size)
|
||||
{
|
||||
/* Reserve a free slot for our new object */
|
||||
uint16_t free_slot_id;
|
||||
struct slot_header slot_hdr;
|
||||
if (logfs_reserve_free_slot (&free_slot_id, &slot_hdr, obj_id, obj_inst_id, obj_size) != 0) {
|
||||
if (logfs_reserve_free_slot (logfs, &free_slot_id, &slot_hdr, obj_id, obj_inst_id, obj_size) != 0) {
|
||||
/* Failed to reserve a free slot */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compute slot address */
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, free_slot_id);
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs, logfs->active_arena_id, free_slot_id);
|
||||
|
||||
/* Write the data into the reserved slot, starting after the slot header */
|
||||
uintptr_t slot_offset = sizeof(slot_hdr);
|
||||
while (obj_size > 0) {
|
||||
/* Individual writes must fit entirely within a single page buffer. */
|
||||
uint16_t page_remaining = logfs.cfg->page_size - (slot_offset % logfs.cfg->page_size);
|
||||
uint16_t page_remaining = logfs->cfg->page_size - (slot_offset % logfs->cfg->page_size);
|
||||
uint16_t write_size = MIN(obj_size, page_remaining);
|
||||
if (logfs.driver->write_data (logfs.flash_id,
|
||||
if (logfs->driver->write_data (logfs->flash_id,
|
||||
slot_addr + slot_offset,
|
||||
obj_data,
|
||||
write_size) != 0) {
|
||||
@ -793,7 +870,7 @@ static int8_t logfs_append_to_log (uint32_t obj_id, uint16_t obj_inst_id, uint8_
|
||||
|
||||
/* Mark this slot active in one atomic step */
|
||||
slot_hdr.state = SLOT_STATE_ACTIVE;
|
||||
if (logfs.driver->write_data (logfs.flash_id,
|
||||
if (logfs->driver->write_data (logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof(slot_hdr)) != 0) {
|
||||
@ -802,7 +879,7 @@ static int8_t logfs_append_to_log (uint32_t obj_id, uint16_t obj_inst_id, uint8_
|
||||
}
|
||||
|
||||
/* Object has been successfully written to the slot */
|
||||
logfs.num_active_slots++;
|
||||
logfs->num_active_slots++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -822,26 +899,34 @@ static int8_t logfs_append_to_log (uint32_t obj_id, uint16_t obj_inst_id, uint8_
|
||||
* @param[in] obj_data Contents of the object being saved
|
||||
* @param[in] obj_size Size of the object being saved
|
||||
* @return 0 if success or error code
|
||||
* @retval -1 if failed to start transaction
|
||||
* @retval -2 if failure to delete any previous versions of the object
|
||||
* @retval -3 if filesystem is entirely full and garbage collection won't help
|
||||
* @retval -4 if garbage collection failed
|
||||
* @retval -5 if filesystem is full even after garbage collection should have freed space
|
||||
* @retval -6 if writing the new object to the filesystem failed
|
||||
* @retval -1 if fs_id is not a valid filesystem instance
|
||||
* @retval -2 if failed to start transaction
|
||||
* @retval -3 if failure to delete any previous versions of the object
|
||||
* @retval -4 if filesystem is entirely full and garbage collection won't help
|
||||
* @retval -5 if garbage collection failed
|
||||
* @retval -6 if filesystem is full even after garbage collection should have freed space
|
||||
* @retval -7 if writing the new object to the filesystem failed
|
||||
*/
|
||||
int32_t PIOS_FLASHFS_ObjSave(__attribute__((unused)) uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size)
|
||||
int32_t PIOS_FLASHFS_ObjSave(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size)
|
||||
{
|
||||
int8_t rc;
|
||||
|
||||
PIOS_Assert(obj_size <= (logfs.cfg->slot_size - sizeof(struct slot_header)));
|
||||
struct logfs_state * logfs = (struct logfs_state *)fs_id;
|
||||
|
||||
if (logfs.driver->start_transaction(logfs.flash_id) != 0) {
|
||||
if (!PIOS_FLASHFS_Logfs_validate(logfs)) {
|
||||
rc = -1;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
if (logfs_delete_object (obj_id, obj_inst_id) != 0) {
|
||||
PIOS_Assert(obj_size <= (logfs->cfg->slot_size - sizeof(struct slot_header)));
|
||||
|
||||
if (logfs->driver->start_transaction(logfs->flash_id) != 0) {
|
||||
rc = -2;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
if (logfs_delete_object (logfs, obj_id, obj_inst_id) != 0) {
|
||||
rc = -3;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
@ -851,36 +936,36 @@ int32_t PIOS_FLASHFS_ObjSave(__attribute__((unused)) uint32_t fs_id, uint32_t ob
|
||||
*/
|
||||
|
||||
/* Check if the arena is entirely full. */
|
||||
if (logfs_fs_is_full()) {
|
||||
if (logfs_fs_is_full(logfs)) {
|
||||
/* Note: Filesystem Full means we're full of *active* records so gc won't help at all. */
|
||||
rc = -3;
|
||||
rc = -4;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
/* Is garbage collection required? */
|
||||
if (logfs_log_is_full()) {
|
||||
if (logfs_log_is_full(logfs)) {
|
||||
/* Note: Log Full means the log is full but may contain obsolete slots so gc may free some space */
|
||||
if (logfs_garbage_collect() != 0) {
|
||||
rc = -4;
|
||||
if (logfs_garbage_collect(logfs) != 0) {
|
||||
rc = -5;
|
||||
goto out_end_trans;
|
||||
}
|
||||
/* Check one more time just to be sure we actually free'd some space */
|
||||
if (logfs_log_is_full()) {
|
||||
if (logfs_log_is_full(logfs)) {
|
||||
/*
|
||||
* Log is still full even after gc!
|
||||
* NOTE: This should not happen since the filesystem wasn't full
|
||||
* when we checked above so gc should have helped.
|
||||
*/
|
||||
PIOS_DEBUG_Assert(0);
|
||||
rc = -5;
|
||||
rc = -6;
|
||||
goto out_end_trans;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have room for our new object. Append it to the log. */
|
||||
if (logfs_append_to_log(obj_id, obj_inst_id, obj_data, obj_size) != 0) {
|
||||
if (logfs_append_to_log(logfs, obj_id, obj_inst_id, obj_data, obj_size) != 0) {
|
||||
/* Error during append */
|
||||
rc = -6;
|
||||
rc = -7;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
@ -888,7 +973,7 @@ int32_t PIOS_FLASHFS_ObjSave(__attribute__((unused)) uint32_t fs_id, uint32_t ob
|
||||
rc = 0;
|
||||
|
||||
out_end_trans:
|
||||
logfs.driver->end_transaction(logfs.flash_id);
|
||||
logfs->driver->end_transaction(logfs->flash_id);
|
||||
|
||||
out_exit:
|
||||
return rc;
|
||||
@ -902,47 +987,55 @@ out_exit:
|
||||
* @param[in] obj_data Buffer to hold the contents of the loaded object
|
||||
* @param[in] obj_size Size of the object to be loaded
|
||||
* @return 0 if success or error code
|
||||
* @retval -1 if failed to start transaction
|
||||
* @retval -2 if object not found in filesystem
|
||||
* @retval -3 if object size in filesystem does not exactly match buffer size
|
||||
* @retval -4 if reading the object data from flash fails
|
||||
* @retval -1 if fs_id is not a valid filesystem instance
|
||||
* @retval -2 if failed to start transaction
|
||||
* @retval -3 if object not found in filesystem
|
||||
* @retval -4 if object size in filesystem does not exactly match buffer size
|
||||
* @retval -5 if reading the object data from flash fails
|
||||
*/
|
||||
int32_t PIOS_FLASHFS_ObjLoad(__attribute__((unused)) uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size)
|
||||
int32_t PIOS_FLASHFS_ObjLoad(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size)
|
||||
{
|
||||
int8_t rc;
|
||||
|
||||
PIOS_Assert(obj_size <= (logfs.cfg->slot_size - sizeof(struct slot_header)));
|
||||
struct logfs_state * logfs = (struct logfs_state *)fs_id;
|
||||
|
||||
if (logfs.driver->start_transaction(logfs.flash_id) != 0) {
|
||||
if (!PIOS_FLASHFS_Logfs_validate(logfs)) {
|
||||
rc = -1;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
PIOS_Assert(obj_size <= (logfs->cfg->slot_size - sizeof(struct slot_header)));
|
||||
|
||||
if (logfs->driver->start_transaction(logfs->flash_id) != 0) {
|
||||
rc = -2;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
/* Find the object in the log */
|
||||
uint16_t slot_id = 0;
|
||||
struct slot_header slot_hdr;
|
||||
if (logfs_object_find_next (&slot_hdr, &slot_id, obj_id, obj_inst_id) != 0) {
|
||||
if (logfs_object_find_next (logfs, &slot_hdr, &slot_id, obj_id, obj_inst_id) != 0) {
|
||||
/* Object does not exist in fs */
|
||||
rc = -2;
|
||||
rc = -3;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
/* Sanity check what we've found */
|
||||
if (slot_hdr.obj_size != obj_size) {
|
||||
/* Object sizes don't match. Not safe to copy contents. */
|
||||
rc = -3;
|
||||
rc = -4;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
/* Read the contents of the object from the log */
|
||||
if (obj_size > 0) {
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id);
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
uintptr_t slot_addr = logfs_get_addr (logfs, logfs->active_arena_id, slot_id);
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
slot_addr + sizeof(slot_hdr),
|
||||
(uint8_t *)obj_data,
|
||||
obj_size) != 0) {
|
||||
/* Failed to read object data from the log */
|
||||
rc = -4;
|
||||
rc = -5;
|
||||
goto out_end_trans;
|
||||
}
|
||||
}
|
||||
@ -951,7 +1044,7 @@ int32_t PIOS_FLASHFS_ObjLoad(__attribute__((unused)) uint32_t fs_id, uint32_t ob
|
||||
rc = 0;
|
||||
|
||||
out_end_trans:
|
||||
logfs.driver->end_transaction(logfs.flash_id);
|
||||
logfs->driver->end_transaction(logfs->flash_id);
|
||||
|
||||
out_exit:
|
||||
return rc;
|
||||
@ -963,20 +1056,28 @@ out_exit:
|
||||
* @param[in] obj UAVObject ID of the object to delete
|
||||
* @param[in] obj_inst_id The instance of the object to delete
|
||||
* @return 0 if success or error code
|
||||
* @retval -1 if failed to start transaction
|
||||
* @retval -2 if failed to delete the object from the filesystem
|
||||
* @retval -1 if fs_id is not a valid filesystem instance
|
||||
* @retval -2 if failed to start transaction
|
||||
* @retval -3 if failed to delete the object from the filesystem
|
||||
*/
|
||||
int32_t PIOS_FLASHFS_ObjDelete(__attribute__((unused)) uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id)
|
||||
int32_t PIOS_FLASHFS_ObjDelete(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id)
|
||||
{
|
||||
int8_t rc;
|
||||
|
||||
if (logfs.driver->start_transaction(logfs.flash_id) != 0) {
|
||||
struct logfs_state * logfs = (struct logfs_state *)fs_id;
|
||||
|
||||
if (!PIOS_FLASHFS_Logfs_validate(logfs)) {
|
||||
rc = -1;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
if (logfs_delete_object (obj_id, obj_inst_id) != 0) {
|
||||
if (logfs->driver->start_transaction(logfs->flash_id) != 0) {
|
||||
rc = -2;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
if (logfs_delete_object (logfs, obj_id, obj_inst_id) != 0) {
|
||||
rc = -3;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
@ -984,7 +1085,7 @@ int32_t PIOS_FLASHFS_ObjDelete(__attribute__((unused)) uint32_t fs_id, uint32_t
|
||||
rc = 0;
|
||||
|
||||
out_end_trans:
|
||||
logfs.driver->end_transaction(logfs.flash_id);
|
||||
logfs->driver->end_transaction(logfs->flash_id);
|
||||
|
||||
out_exit:
|
||||
return rc;
|
||||
@ -994,46 +1095,54 @@ out_exit:
|
||||
* @brief Erases all filesystem arenas and activate the first arena
|
||||
* @param[in] fs_id The filesystem to use for this action
|
||||
* @return 0 if success or error code
|
||||
* @retval -1 if failed to start transaction
|
||||
* @retval -2 if failed to erase all arenas
|
||||
* @retval -3 if failed to activate arena 0
|
||||
* @retval -4 if failed to mount arena 0
|
||||
* @retval -1 if fs_id is not a valid filesystem instance
|
||||
* @retval -2 if failed to start transaction
|
||||
* @retval -3 if failed to erase all arenas
|
||||
* @retval -4 if failed to activate arena 0
|
||||
* @retval -5 if failed to mount arena 0
|
||||
*/
|
||||
int32_t PIOS_FLASHFS_Format(__attribute__((unused)) uint32_t fs_id)
|
||||
int32_t PIOS_FLASHFS_Format(uintptr_t fs_id)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
if (logfs.mounted) {
|
||||
logfs_unmount_log();
|
||||
}
|
||||
struct logfs_state * logfs = (struct logfs_state *)fs_id;
|
||||
|
||||
if (logfs.driver->start_transaction(logfs.flash_id) != 0) {
|
||||
if (!PIOS_FLASHFS_Logfs_validate(logfs)) {
|
||||
rc = -1;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
if (logfs_erase_all_arenas() != 0) {
|
||||
rc = -2;
|
||||
goto out_end_trans;
|
||||
if (logfs->mounted) {
|
||||
logfs_unmount_log(logfs);
|
||||
}
|
||||
|
||||
/* Reinitialize arena 0 */
|
||||
if (logfs_activate_arena(0) != 0) {
|
||||
if (logfs->driver->start_transaction(logfs->flash_id) != 0) {
|
||||
rc = -2;
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
if (logfs_erase_all_arenas(logfs) != 0) {
|
||||
rc = -3;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
/* Mount arena 0 */
|
||||
if (logfs_mount_log(0) != 0) {
|
||||
/* Reinitialize arena 0 */
|
||||
if (logfs_activate_arena(logfs, 0) != 0) {
|
||||
rc = -4;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
/* Mount arena 0 */
|
||||
if (logfs_mount_log(logfs, 0) != 0) {
|
||||
rc = -5;
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
/* Chip erased and log remounted successfully */
|
||||
rc = 0;
|
||||
|
||||
out_end_trans:
|
||||
logfs.driver->end_transaction(logfs.flash_id);
|
||||
logfs->driver->end_transaction(logfs->flash_id);
|
||||
|
||||
out_exit:
|
||||
return rc;
|
||||
|
@ -29,9 +29,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int32_t PIOS_FLASHFS_Format(uint32_t fs_id);
|
||||
int32_t PIOS_FLASHFS_ObjSave(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size);
|
||||
int32_t PIOS_FLASHFS_ObjLoad(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size);
|
||||
int32_t PIOS_FLASHFS_ObjDelete(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id);
|
||||
int32_t PIOS_FLASHFS_Format(uintptr_t fs_id);
|
||||
int32_t PIOS_FLASHFS_ObjSave(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size);
|
||||
int32_t PIOS_FLASHFS_ObjLoad(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size);
|
||||
int32_t PIOS_FLASHFS_ObjDelete(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id);
|
||||
|
||||
#endif /* PIOS_FLASHFS_H */
|
||||
|
@ -43,4 +43,6 @@ struct flashfs_logfs_cfg {
|
||||
|
||||
int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uintptr_t flash_id);
|
||||
|
||||
int32_t PIOS_FLASHFS_Logfs_Destroy(uintptr_t fs_id);
|
||||
|
||||
#endif /* PIOS_FLASHFS_LOGFS_PRIV_H */
|
||||
|
@ -279,12 +279,15 @@
|
||||
#endif
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH
|
||||
/* #define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS */
|
||||
/* #define PIOS_INCLUDE_FLASH_LOGFS_SETTINGS */
|
||||
/* #define FLASH_FREERTOS */
|
||||
#include <pios_flash.h>
|
||||
#include <pios_flashfs.h>
|
||||
#endif
|
||||
|
||||
/* driver for storage on internal flash */
|
||||
/* #define PIOS_INCLUDE_FLASH_INTERNAL */
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH_EEPROM
|
||||
#include <pios_eeprom.h>
|
||||
#endif
|
||||
|
@ -2,7 +2,7 @@ MEMORY
|
||||
{
|
||||
BL_FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x03000 - 0x00080
|
||||
BD_INFO (r) : ORIGIN = 0x08003000 - 0x80, LENGTH = 0x00080
|
||||
FLASH (rx) : ORIGIN = 0x08003000, LENGTH = 0x20000 - 0x03000 - 0x00400
|
||||
EE_FLASH (rw) : ORIGIN = 0x0801FC00, LENGTH = 0x00400
|
||||
FLASH (rx) : ORIGIN = 0x08003000, LENGTH = 0x20000 - 0x03000 - 0x04000
|
||||
EE_FLASH (rw) : ORIGIN = 0x0801C000, LENGTH = 0x04000
|
||||
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x05000
|
||||
}
|
||||
|
291
flight/pios/stm32f10x/pios_flash_internal.c
Normal file
291
flight/pios/stm32f10x/pios_flash_internal.c
Normal file
@ -0,0 +1,291 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_flash_internal.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
|
||||
* @brief brief goes here.
|
||||
* --
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH_INTERNAL
|
||||
|
||||
#include "stm32f10x_flash.h"
|
||||
#include "pios_flash_internal_priv.h"
|
||||
#include "pios_flash.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
struct device_flash_sector {
|
||||
uint32_t start;
|
||||
uint32_t size;
|
||||
uint16_t st_sector;
|
||||
};
|
||||
|
||||
static bool PIOS_Flash_Internal_GetSectorInfo(uint32_t address, uint8_t * sector_number, uint32_t *sector_start, uint32_t *sector_size)
|
||||
{
|
||||
uint16_t sector = (address - 0x08000000) / 1024;
|
||||
if(sector <= 127) {
|
||||
/* address lies within this sector */
|
||||
*sector_number = sector;
|
||||
*sector_start = sector * 1024 + 0x08000000;
|
||||
*sector_size = 1024;
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
enum pios_internal_flash_dev_magic {
|
||||
PIOS_INTERNAL_FLASH_DEV_MAGIC = 0x33445902,
|
||||
};
|
||||
|
||||
struct pios_internal_flash_dev {
|
||||
enum pios_internal_flash_dev_magic magic;
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
xSemaphoreHandle transaction_lock;
|
||||
#endif /* defined(PIOS_INCLUDE_FREERTOS) */
|
||||
};
|
||||
|
||||
static bool PIOS_Flash_Internal_Validate(struct pios_internal_flash_dev * flash_dev) {
|
||||
return (flash_dev && (flash_dev->magic == PIOS_INTERNAL_FLASH_DEV_MAGIC));
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
static struct pios_internal_flash_dev * PIOS_Flash_Internal_alloc(void)
|
||||
{
|
||||
struct pios_internal_flash_dev * flash_dev;
|
||||
|
||||
flash_dev = (struct pios_internal_flash_dev *)pvPortMalloc(sizeof(* flash_dev));
|
||||
if (!flash_dev) return (NULL);
|
||||
|
||||
flash_dev->magic = PIOS_INTERNAL_FLASH_DEV_MAGIC;
|
||||
|
||||
return(flash_dev);
|
||||
}
|
||||
#else
|
||||
static struct pios_internal_flash_dev pios_internal_flash_devs[PIOS_INTERNAL_FLASH_MAX_DEVS];
|
||||
static uint8_t pios_internal_flash_num_devs;
|
||||
static struct pios_internal_flash_dev * PIOS_Flash_Internal_alloc(void)
|
||||
{
|
||||
struct pios_internal_flash_dev * flash_dev;
|
||||
|
||||
if (pios_internal_flash_num_devs >= PIOS_INTERNAL_FLASH_MAX_DEVS) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
flash_dev = &pios_internal_flash_devs[pios_internal_flash_num_devs++];
|
||||
flash_dev->magic = PIOS_INTERNAL_FLASH_DEV_MAGIC;
|
||||
|
||||
return (flash_dev);
|
||||
}
|
||||
|
||||
#endif /* defined(PIOS_INCLUDE_FREERTOS) */
|
||||
|
||||
int32_t PIOS_Flash_Internal_Init(uintptr_t * flash_id, __attribute__((unused)) const struct pios_flash_internal_cfg * cfg)
|
||||
{
|
||||
struct pios_internal_flash_dev * flash_dev;
|
||||
|
||||
flash_dev = PIOS_Flash_Internal_alloc();
|
||||
if (flash_dev == NULL)
|
||||
return -1;
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
flash_dev->transaction_lock = xSemaphoreCreateMutex();
|
||||
#endif /* defined(PIOS_INCLUDE_FREERTOS) */
|
||||
|
||||
*flash_id = (uintptr_t) flash_dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
*
|
||||
* Provide a PIOS flash driver API
|
||||
*
|
||||
*********************************/
|
||||
#include "pios_flash.h"
|
||||
|
||||
static int32_t PIOS_Flash_Internal_StartTransaction(uintptr_t flash_id)
|
||||
{
|
||||
struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id;
|
||||
|
||||
if (!PIOS_Flash_Internal_Validate(flash_dev))
|
||||
return -1;
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
if (xSemaphoreTake(flash_dev->transaction_lock, portMAX_DELAY) != pdTRUE)
|
||||
return -2;
|
||||
#endif /* defined(PIOS_INCLUDE_FREERTOS) */
|
||||
|
||||
/* Unlock the internal flash so we can write to it */
|
||||
FLASH_Unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t PIOS_Flash_Internal_EndTransaction(uintptr_t flash_id)
|
||||
{
|
||||
struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id;
|
||||
|
||||
if (!PIOS_Flash_Internal_Validate(flash_dev))
|
||||
return -1;
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
if (xSemaphoreGive(flash_dev->transaction_lock) != pdTRUE)
|
||||
return -2;
|
||||
#endif /* defined(PIOS_INCLUDE_FREERTOS) */
|
||||
|
||||
/* Lock the internal flash again so we can no longer write to it */
|
||||
FLASH_Lock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t PIOS_Flash_Internal_EraseSector(uintptr_t flash_id, uint32_t addr)
|
||||
{
|
||||
struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id;
|
||||
|
||||
if (!PIOS_Flash_Internal_Validate(flash_dev))
|
||||
return -1;
|
||||
|
||||
uint8_t sector_number;
|
||||
uint32_t sector_start;
|
||||
uint32_t sector_size;
|
||||
if (!PIOS_Flash_Internal_GetSectorInfo(addr,
|
||||
§or_number,
|
||||
§or_start,
|
||||
§or_size)) {
|
||||
/* We're asking for an invalid flash address */
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (FLASH_ErasePage(sector_start) != FLASH_COMPLETE)
|
||||
return -3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t PIOS_Flash_Internal_WriteData(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len)
|
||||
{
|
||||
PIOS_Assert(data);
|
||||
|
||||
struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id;
|
||||
|
||||
if (!PIOS_Flash_Internal_Validate(flash_dev))
|
||||
return -1;
|
||||
|
||||
uint8_t sector_number;
|
||||
uint32_t sector_start;
|
||||
uint32_t sector_size;
|
||||
uint32_t hword_data;
|
||||
uint32_t offset;
|
||||
|
||||
/* Ensure that the base address is in a valid sector */
|
||||
if (!PIOS_Flash_Internal_GetSectorInfo(addr,
|
||||
§or_number,
|
||||
§or_start,
|
||||
§or_size)) {
|
||||
/* We're asking for an invalid flash address */
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Ensure that the entire write occurs within the same sector */
|
||||
if ((uintptr_t)addr + len > sector_start + sector_size) {
|
||||
/* Write crosses the end of the sector */
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Write the data */
|
||||
uint32_t temp_addr = addr;
|
||||
uint16_t numberOfhWords = len / 2;
|
||||
uint16_t x = 0;
|
||||
FLASH_Status status;
|
||||
for ( x = 0; x < numberOfhWords; ++x) {
|
||||
offset = 2 * x;
|
||||
hword_data = (data[offset + 1] << 8) | data[offset];
|
||||
|
||||
if(hword_data != *(uint16_t *)(temp_addr + offset)) {
|
||||
status = FLASH_ProgramHalfWord(temp_addr + offset, hword_data);
|
||||
} else {
|
||||
status = FLASH_COMPLETE;
|
||||
}
|
||||
PIOS_Assert(status == FLASH_COMPLETE);
|
||||
}
|
||||
|
||||
uint16_t mod = len % 2;
|
||||
if(mod == 1) {
|
||||
offset = 2 * x;
|
||||
hword_data = 0xFF00 | data[offset];
|
||||
if(hword_data != *(uint16_t *)(temp_addr + offset)) {
|
||||
status = FLASH_ProgramHalfWord(temp_addr + offset, hword_data);
|
||||
} else {
|
||||
status = FLASH_COMPLETE;
|
||||
}
|
||||
PIOS_Assert(status == FLASH_COMPLETE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t PIOS_Flash_Internal_ReadData(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len)
|
||||
{
|
||||
PIOS_Assert(data);
|
||||
|
||||
struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id;
|
||||
|
||||
if (!PIOS_Flash_Internal_Validate(flash_dev))
|
||||
return -1;
|
||||
|
||||
uint8_t sector_number;
|
||||
uint32_t sector_start;
|
||||
uint32_t sector_size;
|
||||
|
||||
/* Ensure that the base address is in a valid sector */
|
||||
if (!PIOS_Flash_Internal_GetSectorInfo(addr,
|
||||
§or_number,
|
||||
§or_start,
|
||||
§or_size)) {
|
||||
/* We're asking for an invalid flash address */
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Ensure that the entire read occurs within the same sector */
|
||||
if ((uintptr_t)addr + len > sector_start + sector_size) {
|
||||
/* Read crosses the end of the sector */
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Read the data into the buffer directly */
|
||||
memcpy(data, (void *)addr, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Provide a flash driver to external drivers */
|
||||
const struct pios_flash_driver pios_internal_flash_driver = {
|
||||
.start_transaction = PIOS_Flash_Internal_StartTransaction,
|
||||
.end_transaction = PIOS_Flash_Internal_EndTransaction,
|
||||
.erase_sector = PIOS_Flash_Internal_EraseSector,
|
||||
.write_data = PIOS_Flash_Internal_WriteData,
|
||||
.read_data = PIOS_Flash_Internal_ReadData,
|
||||
};
|
||||
|
||||
#endif /* PIOS_INCLUDE_FLASH_INTERNAL */
|
@ -276,16 +276,20 @@ static int32_t PIOS_Flash_Internal_WriteData(uintptr_t flash_id, uint32_t addr,
|
||||
/* Write crosses the end of the sector */
|
||||
return -3;
|
||||
}
|
||||
FLASH_Status status;
|
||||
for (uint16_t i = 0; i < len/4; i++){
|
||||
uint32_t data_word = *(uint32_t *)(data + i*4);
|
||||
status = FLASH_ProgramWord(addr + i * 4, data_word);
|
||||
if(status != FLASH_COMPLETE)
|
||||
return -4;
|
||||
}
|
||||
|
||||
/* Write the data */
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
FLASH_Status status;
|
||||
/*
|
||||
* This is inefficient. Should try to do word writes.
|
||||
* Not sure if word writes need to be aligned though.
|
||||
*/
|
||||
for (uint16_t i = len - len % 4; i < len; i++) {
|
||||
|
||||
status = FLASH_ProgramByte(addr + i, data[i]);
|
||||
PIOS_Assert(status == FLASH_COMPLETE);
|
||||
if(status != FLASH_COMPLETE)
|
||||
return -5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -168,6 +168,20 @@ void PIOS_USBHOOK_RegisterEpOutCallback(uint8_t epnum, uint16_t max_len, pios_us
|
||||
/*
|
||||
* FIXME do not hardcode endpoint type
|
||||
*/
|
||||
|
||||
/*
|
||||
* Make sure we refuse OUT transactions until we explicitly
|
||||
* connect a receive buffer with PIOS_USBHOOK_EndpointRx().
|
||||
*
|
||||
* Without this, the ST USB code will receive on this endpoint
|
||||
* and blindly write the data to a NULL pointer which will
|
||||
* have the side effect of placing the internal flash into an
|
||||
* errored state. Address 0x0000_0000 is aliased into internal
|
||||
* flash via the "Section 2.4 Boot configuration" BOOT0/1 pins.
|
||||
*/
|
||||
DCD_SetEPStatus(&pios_usb_otg_core_handle,
|
||||
epnum,
|
||||
USB_OTG_EP_RX_NAK);
|
||||
}
|
||||
|
||||
extern void PIOS_USBHOOK_DeRegisterEpOutCallback(uint8_t epnum)
|
||||
|
@ -107,9 +107,10 @@
|
||||
/* #define PIOS_INCLUDE_SDCARD */
|
||||
/* #define LOG_FILENAME "startup.log" */
|
||||
#define PIOS_INCLUDE_FLASH
|
||||
#define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS
|
||||
#define PIOS_INCLUDE_FLASH_LOGFS_SETTINGS
|
||||
/* #define FLASH_FREERTOS */
|
||||
/* #define PIOS_INCLUDE_FLASH_EEPROM */
|
||||
/* #define PIOS_INCLUDE_FLASH_INTERNAL */
|
||||
|
||||
/* PIOS radio modules */
|
||||
/* #define PIOS_INCLUDE_RFM22B */
|
||||
|
@ -76,6 +76,8 @@ uint32_t pios_com_hkosd_id;
|
||||
|
||||
uint32_t pios_usb_rctx_id;
|
||||
|
||||
uintptr_t pios_uavo_settings_fs_id;
|
||||
|
||||
/**
|
||||
* Configuration for MPU6000 chip
|
||||
*/
|
||||
@ -169,13 +171,12 @@ void PIOS_Board_Init(void) {
|
||||
#endif
|
||||
|
||||
uintptr_t flash_id;
|
||||
uintptr_t fs_id;
|
||||
switch(bdinfo->board_rev) {
|
||||
case BOARD_REVISION_CC:
|
||||
if (PIOS_Flash_Jedec_Init(&flash_id, pios_spi_flash_accel_id, 1)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
if (PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_w25x_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
if (PIOS_FLASHFS_Logfs_Init(&pios_uavo_settings_fs_id, &flashfs_w25x_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
break;
|
||||
@ -183,7 +184,7 @@ void PIOS_Board_Init(void) {
|
||||
if (PIOS_Flash_Jedec_Init(&flash_id, pios_spi_flash_accel_id, 0)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
if (PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
if (PIOS_FLASHFS_Logfs_Init(&pios_uavo_settings_fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
break;
|
||||
@ -205,7 +206,7 @@ void PIOS_Board_Init(void) {
|
||||
PIOS_IAP_ReadBootCmd(1) == PIOS_IAP_CLEAR_FLASH_CMD_1 &&
|
||||
PIOS_IAP_ReadBootCmd(2) == PIOS_IAP_CLEAR_FLASH_CMD_2)
|
||||
{
|
||||
PIOS_FLASHFS_Format(fs_id);
|
||||
PIOS_FLASHFS_Format(pios_uavo_settings_fs_id);
|
||||
PIOS_IAP_WriteBootCmd(0,0);
|
||||
PIOS_IAP_WriteBootCmd(1,0);
|
||||
PIOS_IAP_WriteBootCmd(2,0);
|
||||
|
@ -12,13 +12,28 @@ MODEL_SUFFIX := _PX
|
||||
OPENOCD_JTAG_CONFIG := stlink-v2.cfg
|
||||
OPENOCD_CONFIG := stm32f1x.stlink.cfg
|
||||
|
||||
# Flash memory map for OPLM:
|
||||
# Sector start size use
|
||||
# 0 0x0800 0000 1k BL
|
||||
# 1 0x0800 0400 1k BL
|
||||
# .. ..
|
||||
# 10 0x0800 2C00 1k BL
|
||||
# 11 0x0800 3000 1k FW
|
||||
# 12 0x0800 1000 1k FW
|
||||
# .. ..
|
||||
# 125 0x0801 F400 1k FW
|
||||
# 126 0x0801 F800 1k EE
|
||||
# 127 0x0801 FC00 1k EE
|
||||
|
||||
|
||||
# Note: These must match the values in link_$(BOARD)_memory.ld
|
||||
BL_BANK_BASE := 0x08000000 # Start of bootloader flash
|
||||
BL_BANK_SIZE := 0x00003000 # Should include BD_INFO region
|
||||
FW_BANK_BASE := 0x08003000 # Start of firmware flash
|
||||
FW_BANK_SIZE := 0x0001CC00 # Should include FW_DESC_SIZE
|
||||
EE_BANK_BASE := 0x0801FC00 # EEPROM storage area
|
||||
EE_BANK_SIZE := 0x00000400 # Size of EEPROM storage area
|
||||
FW_BANK_SIZE := 0x00019000 # Should include FW_DESC_SIZE
|
||||
EE_BANK_BASE := 0x0801C000 # EEPROM storage area
|
||||
EE_BANK_SIZE := 0x00004000 # Size of EEPROM storage area
|
||||
|
||||
FW_DESC_SIZE := 0x00000064
|
||||
|
||||
|
@ -99,6 +99,29 @@ const struct pios_led_cfg * PIOS_BOARD_HW_DEFS_GetLedCfg (__attribute__((unused)
|
||||
|
||||
#endif /* PIOS_INCLUDE_LED */
|
||||
|
||||
#if defined(PIOS_INCLUDE_FLASH)
|
||||
#include "pios_flashfs_logfs_priv.h"
|
||||
#include "pios_flash_internal_priv.h"
|
||||
|
||||
static const struct pios_flash_internal_cfg flash_internal_cfg = {
|
||||
};
|
||||
|
||||
static const struct flashfs_logfs_cfg flashfs_internal_cfg = {
|
||||
.fs_magic = 0x99abcfef,
|
||||
.total_fs_size = EE_BANK_SIZE, /* 2K bytes (2x1KB sectors) */
|
||||
.arena_size = 0x00002000, /* 4 * slot size = 1K bytes = 1 sector */
|
||||
.slot_size = 0x00000100, /* 256 bytes */
|
||||
|
||||
.start_offset = EE_BANK_BASE, /* start after the bootloader */
|
||||
.sector_size = 0x00000400, /* 1K bytes */
|
||||
.page_size = 0x00000400, /* 1K bytes */
|
||||
};
|
||||
|
||||
#include "pios_flash.h"
|
||||
|
||||
#endif /* PIOS_INCLUDE_FLASH */
|
||||
|
||||
|
||||
#if defined(PIOS_INCLUDE_SPI)
|
||||
|
||||
#include <pios_spi_priv.h>
|
||||
|
@ -106,10 +106,11 @@
|
||||
/* #define PIOS_OVERO_SPI */
|
||||
/* #define PIOS_INCLUDE_SDCARD */
|
||||
/* #define LOG_FILENAME "startup.log" */
|
||||
/* #define PIOS_INCLUDE_FLASH */
|
||||
/* #define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS */
|
||||
#define PIOS_INCLUDE_FLASH
|
||||
#define PIOS_INCLUDE_FLASH_INTERNAL
|
||||
#define PIOS_INCLUDE_FLASH_LOGFS_SETTINGS
|
||||
/* #define FLASH_FREERTOS */
|
||||
#define PIOS_INCLUDE_FLASH_EEPROM
|
||||
//#define PIOS_INCLUDE_FLASH_EEPROM
|
||||
|
||||
/* PIOS radio modules */
|
||||
#define PIOS_INCLUDE_RFM22B
|
||||
|
@ -73,6 +73,8 @@ uint32_t pios_com_radio_id = 0;
|
||||
uint8_t *pios_uart_rx_buffer;
|
||||
uint8_t *pios_uart_tx_buffer;
|
||||
|
||||
uintptr_t pios_uavo_settings_fs_id;
|
||||
|
||||
/**
|
||||
* PIOS_Board_Init()
|
||||
* initializes all the core subsystems on this specific hardware
|
||||
@ -83,6 +85,12 @@ void PIOS_Board_Init(void) {
|
||||
/* Delay system */
|
||||
PIOS_DELAY_Init();
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH_LOGFS_SETTINGS
|
||||
uintptr_t flash_id;
|
||||
PIOS_Flash_Internal_Init(&flash_id, &flash_internal_cfg);
|
||||
PIOS_FLASHFS_Logfs_Init(&pios_uavo_settings_fs_id, &flashfs_internal_cfg, &pios_internal_flash_driver, flash_id);
|
||||
#endif
|
||||
|
||||
/* Initialize UAVObject libraries */
|
||||
EventDispatcherInitialize();
|
||||
UAVObjInitialize();
|
||||
@ -109,8 +117,6 @@ void PIOS_Board_Init(void) {
|
||||
#endif /* PIOS_INCLUDE_LED */
|
||||
|
||||
OPLinkSettingsData oplinkSettings;
|
||||
#if defined(PIOS_INCLUDE_FLASH_EEPROM)
|
||||
PIOS_EEPROM_Init(&pios_eeprom_cfg);
|
||||
|
||||
/* IAP System Setup */
|
||||
PIOS_IAP_Init();
|
||||
@ -120,7 +126,8 @@ void PIOS_Board_Init(void) {
|
||||
PIOS_IAP_ReadBootCmd(2) == PIOS_IAP_CLEAR_FLASH_CMD_2) {
|
||||
OPLinkSettingsGet(&oplinkSettings);
|
||||
OPLinkSettingsSetDefaults(&oplinkSettings,0);
|
||||
PIOS_EEPROM_Save((uint8_t*)&oplinkSettings, sizeof(OPLinkSettingsData));
|
||||
OPLinkSettingsSet(&oplinkSettings);
|
||||
//PIOS_EEPROM_Save((uint8_t*)&oplinkSettings, sizeof(OPLinkSettingsData));
|
||||
for (uint32_t i = 0; i < 10; i++) {
|
||||
PIOS_DELAY_WaitmS(100);
|
||||
PIOS_LED_Toggle(PIOS_LED_HEARTBEAT);
|
||||
@ -129,15 +136,8 @@ void PIOS_Board_Init(void) {
|
||||
PIOS_IAP_WriteBootCmd(1,0);
|
||||
PIOS_IAP_WriteBootCmd(2,0);
|
||||
}
|
||||
/* Read the settings from flash. */
|
||||
/* NOTE: We probably need to save/restore the objID here incase the object changed but the size doesn't */
|
||||
if (PIOS_EEPROM_Load((uint8_t*)&oplinkSettings, sizeof(OPLinkSettingsData)) == 0)
|
||||
OPLinkSettingsSet(&oplinkSettings);
|
||||
else
|
||||
OPLinkSettingsGet(&oplinkSettings);
|
||||
#else
|
||||
OPLinkSettingsGet(&oplinkSettings);
|
||||
#endif /* PIOS_INCLUDE_FLASH_EEPROM */
|
||||
|
||||
|
||||
/* Initialize the task monitor */
|
||||
if (PIOS_TASK_MONITOR_Initialize(TASKINFO_RUNNING_NUMELEM)) {
|
||||
|
@ -14,18 +14,19 @@ OPENOCD_CONFIG := stm32f4xx.stlink.cfg
|
||||
#OPENOCD_CONFIG := stm32f4xx.cfg
|
||||
|
||||
# Flash memory map for OSD:
|
||||
# Sector start size use
|
||||
# 0 0x0800 0000 16k BL
|
||||
# 1 0x0800 4000 16k BL
|
||||
# 2 0x0800 8000 16k EE
|
||||
# 3 0x0800 C000 16k EE
|
||||
# 4 0x0801 0000 64k Unused
|
||||
# 5 0x0802 0000 128k FW
|
||||
# 6 0x0804 0000 128k FW
|
||||
# 7 0x0806 0000 128k FW
|
||||
# 8 0x0808 0000 128k Unused
|
||||
# .. ..
|
||||
# 11 0x080E 0000 128k Unused
|
||||
# Sector start size use
|
||||
# 0 0x0800 0000 16k BL
|
||||
# 1 0x0800 4000 16k BL
|
||||
# 2 0x0800 8000 16k EE
|
||||
# 3 0x0800 C000 16k EE
|
||||
# 4 0x0801 0000 64k Unused
|
||||
# 5 0x0802 0000 128k FW
|
||||
# 6 0x0804 0000 128k FW
|
||||
# 7 0x0806 0000 128k FW
|
||||
# 8 0x0808 0000 128k Unused
|
||||
# 9 0x080A 0000 128k Unused
|
||||
# 10 0x080C 0000 128k Unused ..
|
||||
# 11 0x080E 0000 128k Unused
|
||||
|
||||
# Note: These must match the values in link_$(BOARD)_memory.ld
|
||||
BL_BANK_BASE := 0x08000000 # Start of bootloader flash
|
||||
|
@ -99,10 +99,6 @@ else
|
||||
SRC += $(OPTESTS)/test_common.c
|
||||
SRC += $(OPTESTS)/$(TESTAPP).c
|
||||
endif
|
||||
|
||||
CDEFS += -DEE_BANK_BASE=$(EE_BANK_BASE)
|
||||
CDEFS += -DEE_BANK_SIZE=$(EE_BANK_SIZE)
|
||||
|
||||
|
||||
# Optional component libraries
|
||||
include $(PIOS)/common/libraries/dosfs/library.mk
|
||||
|
@ -109,7 +109,7 @@
|
||||
#define LOG_FILENAME "startup.log"
|
||||
#define PIOS_INCLUDE_FLASH
|
||||
#define PIOS_INCLUDE_FLASH_INTERNAL
|
||||
#define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS
|
||||
#define PIOS_INCLUDE_FLASH_LOGFS_SETTINGS
|
||||
/* #define FLASH_FREERTOS */
|
||||
/* #define PIOS_INCLUDE_FLASH_EEPROM */
|
||||
|
||||
|
@ -105,6 +105,8 @@ uint32_t pios_com_gps_id;
|
||||
uint32_t pios_com_telem_usb_id;
|
||||
uint32_t pios_com_telem_rf_id;
|
||||
|
||||
uintptr_t pios_uavo_settings_fs_id;
|
||||
|
||||
/**
|
||||
* TIM3 is triggered by the HSYNC signal into its ETR line and will divide the
|
||||
* APB1_CLOCK to generate a pixel clock that is used by the SPI CLK lines.
|
||||
@ -162,11 +164,10 @@ void PIOS_Board_Init(void) {
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_SPI */
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH_SECTOR_SETTINGS
|
||||
#ifdef PIOS_INCLUDE_FLASH_LOGFS_SETTINGS
|
||||
uintptr_t flash_id;
|
||||
uintptr_t fs_id;
|
||||
PIOS_Flash_Internal_Init(&flash_id, &flash_internal_cfg);
|
||||
PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_internal_cfg, &pios_internal_flash_driver, flash_id);
|
||||
PIOS_FLASHFS_Logfs_Init(&pios_uavo_settings_fs_id, &flashfs_internal_cfg, &pios_internal_flash_driver, flash_id);
|
||||
#elif !defined(PIOS_USE_SETTINGS_ON_SDCARD)
|
||||
#error No setting storage specified. (define PIOS_USE_SETTINGS_ON_SDCARD or INCLUDE_FLASH_SECTOR_SETTINGS)
|
||||
#endif
|
||||
|
@ -12,11 +12,31 @@ MODEL_SUFFIX :=
|
||||
OPENOCD_JTAG_CONFIG := stlink-v2.cfg
|
||||
OPENOCD_CONFIG := stm32f4xx.stlink.cfg
|
||||
|
||||
# Flash memory map for Revolution:
|
||||
# Sector start size use
|
||||
# 0 0x0800 0000 16k BL
|
||||
# 1 0x0800 4000 16k BL
|
||||
# 2 0x0800 8000 16k EE
|
||||
# 3 0x0800 C000 16k EE
|
||||
# 4 0x0801 0000 64k Unused
|
||||
# 5 0x0802 0000 128k FW
|
||||
# 6 0x0804 0000 128k FW
|
||||
# 7 0x0806 0000 128k FW
|
||||
# 8 0x0808 0000 128k Unused
|
||||
# 9 0x080A 0000 128k Unused
|
||||
# 10 0x080C 0000 128k Unused ..
|
||||
# 11 0x080E 0000 128k Unused
|
||||
|
||||
# Note: These must match the values in link_$(BOARD)_memory.ld
|
||||
BL_BANK_BASE := 0x08000000 # Start of bootloader flash
|
||||
BL_BANK_SIZE := 0x00008000 # Should include BD_INFO region
|
||||
|
||||
# Leave the remaining 16KB and 64KB sectors for other uses
|
||||
# 16KB for settings storage
|
||||
|
||||
EE_BANK_BASE := 0x08008000 # EEPROM storage area
|
||||
EE_BANK_SIZE := 0x00008000 # Size of EEPROM storage area
|
||||
|
||||
# Leave the remaining 64KB sectors for other uses
|
||||
|
||||
FW_BANK_BASE := 0x08020000 # Start of firmware flash
|
||||
FW_BANK_SIZE := 0x00060000 # Should include FW_DESC_SIZE
|
||||
|
@ -665,8 +665,9 @@ const struct pios_rfm22b_cfg * PIOS_BOARD_HW_DEFS_GetRfm22Cfg (uint32_t board_re
|
||||
#if defined(PIOS_INCLUDE_FLASH)
|
||||
#include "pios_flashfs_logfs_priv.h"
|
||||
#include "pios_flash_jedec_priv.h"
|
||||
#include "pios_flash_internal_priv.h"
|
||||
|
||||
static const struct flashfs_logfs_cfg flashfs_m25p_cfg = {
|
||||
static const struct flashfs_logfs_cfg flashfs_external_cfg = {
|
||||
.fs_magic = 0x99abceef,
|
||||
.total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */
|
||||
.arena_size = 0x00010000, /* 256 * slot size */
|
||||
@ -677,6 +678,20 @@ static const struct flashfs_logfs_cfg flashfs_m25p_cfg = {
|
||||
.page_size = 0x00000100, /* 256 bytes */
|
||||
};
|
||||
|
||||
|
||||
static const struct pios_flash_internal_cfg flash_internal_cfg = { };
|
||||
|
||||
static const struct flashfs_logfs_cfg flashfs_internal_cfg = {
|
||||
.fs_magic = 0x99abcfef,
|
||||
.total_fs_size = EE_BANK_SIZE, /* 32K bytes (2x16KB sectors) */
|
||||
.arena_size = 0x00004000, /* 64 * slot size = 16K bytes = 1 sector */
|
||||
.slot_size = 0x00000100, /* 256 bytes */
|
||||
|
||||
.start_offset = EE_BANK_BASE, /* start after the bootloader */
|
||||
.sector_size = 0x00004000, /* 16K bytes */
|
||||
.page_size = 0x00004000, /* 16K bytes */
|
||||
};
|
||||
|
||||
#endif /* PIOS_INCLUDE_FLASH */
|
||||
|
||||
#include <pios_usart_priv.h>
|
||||
|
@ -107,7 +107,8 @@
|
||||
/* #define PIOS_INCLUDE_SDCARD */
|
||||
/* #define LOG_FILENAME "startup.log" */
|
||||
#define PIOS_INCLUDE_FLASH
|
||||
#define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS
|
||||
#define PIOS_INCLUDE_FLASH_INTERNAL
|
||||
#define PIOS_INCLUDE_FLASH_LOGFS_SETTINGS
|
||||
#define FLASH_FREERTOS
|
||||
/* #define PIOS_INCLUDE_FLASH_EEPROM */
|
||||
|
||||
|
@ -236,6 +236,9 @@ uint32_t pios_com_hkosd_id = 0;
|
||||
uint32_t pios_rfm22b_id = 0;
|
||||
#endif
|
||||
|
||||
uintptr_t pios_uavo_settings_fs_id;
|
||||
uintptr_t pios_user_fs_id;
|
||||
|
||||
/*
|
||||
* Setup a com port based on the passed cfg, driver and buffer sizes. tx size of -1 make the port rx only
|
||||
*/
|
||||
@ -349,13 +352,23 @@ void PIOS_Board_Init(void) {
|
||||
#if defined(PIOS_INCLUDE_FLASH)
|
||||
/* Connect flash to the appropriate interface and configure it */
|
||||
uintptr_t flash_id;
|
||||
|
||||
// initialize the internal settings storage flash
|
||||
if (PIOS_Flash_Internal_Init(&flash_id, &flash_internal_cfg)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
if (PIOS_FLASHFS_Logfs_Init(&pios_uavo_settings_fs_id, &flashfs_internal_cfg, &pios_internal_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
// Initialize the external USER flash
|
||||
if (PIOS_Flash_Jedec_Init(&flash_id, pios_spi_telem_flash_id, 1)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
uintptr_t fs_id;
|
||||
if (PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
if (PIOS_FLASHFS_Logfs_Init(&pios_user_fs_id, &flashfs_external_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -370,7 +383,7 @@ void PIOS_Board_Init(void) {
|
||||
PIOS_IAP_ReadBootCmd(1) == PIOS_IAP_CLEAR_FLASH_CMD_1 &&
|
||||
PIOS_IAP_ReadBootCmd(2) == PIOS_IAP_CLEAR_FLASH_CMD_2)
|
||||
{
|
||||
PIOS_FLASHFS_Format(fs_id);
|
||||
PIOS_FLASHFS_Format(pios_uavo_settings_fs_id);
|
||||
PIOS_IAP_WriteBootCmd(0,0);
|
||||
PIOS_IAP_WriteBootCmd(1,0);
|
||||
PIOS_IAP_WriteBootCmd(2,0);
|
||||
|
@ -16,7 +16,12 @@ OPENOCD_CONFIG := stm32f4xx.stlink.cfg
|
||||
BL_BANK_BASE := 0x08000000 # Start of bootloader flash
|
||||
BL_BANK_SIZE := 0x00008000 # Should include BD_INFO region
|
||||
|
||||
# Leave the remaining 16KB and 64KB sectors for other uses
|
||||
# 16KB for settings storage
|
||||
|
||||
EE_BANK_BASE := 0x08008000 # EEPROM storage area
|
||||
EE_BANK_SIZE := 0x00008000 # Size of EEPROM storage area
|
||||
|
||||
# Leave the remaining 64KB sectors for other uses
|
||||
|
||||
FW_BANK_BASE := 0x08020000 # Start of firmware flash
|
||||
FW_BANK_SIZE := 0x00060000 # Should include FW_DESC_SIZE
|
||||
|
@ -448,16 +448,31 @@ void PIOS_SPI_flash_irq_handler(void)
|
||||
#if defined(PIOS_INCLUDE_FLASH)
|
||||
#include "pios_flashfs_logfs_priv.h"
|
||||
#include "pios_flash_jedec_priv.h"
|
||||
#include "pios_flash_internal_priv.h"
|
||||
|
||||
static const struct flashfs_logfs_cfg flashfs_m25p_cfg = {
|
||||
.fs_magic = 0x99abceef,
|
||||
.total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */
|
||||
.arena_size = 0x00010000, /* 256 * slot size */
|
||||
.slot_size = 0x00000100, /* 256 bytes */
|
||||
static const struct flashfs_logfs_cfg flashfs_external_cfg = {
|
||||
.fs_magic = 0x99abceef,
|
||||
.total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */
|
||||
.arena_size = 0x00010000, /* 256 * slot size */
|
||||
.slot_size = 0x00000100, /* 256 bytes */
|
||||
|
||||
.start_offset = 0, /* start at the beginning of the chip */
|
||||
.sector_size = 0x00010000, /* 64K bytes */
|
||||
.page_size = 0x00000100, /* 256 bytes */
|
||||
.start_offset = 0, /* start at the beginning of the chip */
|
||||
.sector_size = 0x00010000, /* 64K bytes */
|
||||
.page_size = 0x00000100, /* 256 bytes */
|
||||
};
|
||||
|
||||
|
||||
static const struct pios_flash_internal_cfg flash_internal_cfg = { };
|
||||
|
||||
static const struct flashfs_logfs_cfg flashfs_internal_cfg = {
|
||||
.fs_magic = 0x99abcfef,
|
||||
.total_fs_size = EE_BANK_SIZE, /* 32K bytes (2x16KB sectors) */
|
||||
.arena_size = 0x00004000, /* 64 * slot size = 16K bytes = 1 sector */
|
||||
.slot_size = 0x00000100, /* 256 bytes */
|
||||
|
||||
.start_offset = EE_BANK_BASE, /* start after the bootloader */
|
||||
.sector_size = 0x00004000, /* 16K bytes */
|
||||
.page_size = 0x00004000, /* 16K bytes */
|
||||
};
|
||||
|
||||
#endif /* PIOS_INCLUDE_FLASH */
|
||||
|
@ -107,7 +107,8 @@
|
||||
/* #define PIOS_INCLUDE_SDCARD */
|
||||
/* #define LOG_FILENAME "startup.log" */
|
||||
#define PIOS_INCLUDE_FLASH
|
||||
#define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS
|
||||
#define PIOS_INCLUDE_FLASH_INTERNAL
|
||||
#define PIOS_INCLUDE_FLASH_LOGFS_SETTINGS
|
||||
#define FLASH_FREERTOS
|
||||
/* #define PIOS_INCLUDE_FLASH_EEPROM */
|
||||
|
||||
|
@ -306,6 +306,10 @@ uint32_t pios_com_bridge_id = 0;
|
||||
uint32_t pios_com_overo_id = 0;
|
||||
uint32_t pios_com_hkosd_id = 0;
|
||||
|
||||
uintptr_t pios_uavo_settings_fs_id;
|
||||
uintptr_t pios_user_fs_id;
|
||||
|
||||
|
||||
/*
|
||||
* Setup a com port based on the passed cfg, driver and buffer sizes. tx size of -1 make the port rx only
|
||||
*/
|
||||
@ -377,6 +381,18 @@ void PIOS_Board_Init(void) {
|
||||
|
||||
PIOS_LED_Init(&pios_led_cfg);
|
||||
|
||||
/* Connect flash to the appropriate interface and configure it */
|
||||
uintptr_t flash_id;
|
||||
|
||||
// initialize the internal settings storage flash
|
||||
if (PIOS_Flash_Internal_Init(&flash_id, &flash_internal_cfg)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
if (PIOS_FLASHFS_Logfs_Init(&pios_uavo_settings_fs_id, &flashfs_internal_cfg, &pios_internal_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
/* Set up the SPI interface to the accelerometer*/
|
||||
if (PIOS_SPI_Init(&pios_spi_accel_id, &pios_spi_accel_cfg)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
@ -391,22 +407,20 @@ void PIOS_Board_Init(void) {
|
||||
if (PIOS_SPI_Init(&pios_spi_flash_id, &pios_spi_flash_cfg)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
/* Connect flash to the appropriate interface and configure it */
|
||||
uintptr_t flash_id;
|
||||
if (PIOS_Flash_Jedec_Init(&flash_id, pios_spi_flash_id, 0)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
#else
|
||||
/* Connect flash to the appropriate interface and configure it */
|
||||
uintptr_t flash_id;
|
||||
if (PIOS_Flash_Jedec_Init(&flash_id, pios_spi_accel_id, 1)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
#endif
|
||||
uintptr_t fs_id;
|
||||
if (PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
if (PIOS_FLASHFS_Logfs_Init(&pios_user_fs_id, &flashfs_external_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_RTC)
|
||||
PIOS_RTC_Init(&pios_rtc_main_cfg);
|
||||
@ -419,7 +433,7 @@ void PIOS_Board_Init(void) {
|
||||
PIOS_IAP_ReadBootCmd(1) == PIOS_IAP_CLEAR_FLASH_CMD_1 &&
|
||||
PIOS_IAP_ReadBootCmd(2) == PIOS_IAP_CLEAR_FLASH_CMD_2)
|
||||
{
|
||||
PIOS_FLASHFS_Format(fs_id);
|
||||
PIOS_FLASHFS_Format(pios_uavo_settings_fs_id);
|
||||
PIOS_IAP_WriteBootCmd(0,0);
|
||||
PIOS_IAP_WriteBootCmd(1,0);
|
||||
PIOS_IAP_WriteBootCmd(2,0);
|
||||
|
@ -91,7 +91,7 @@
|
||||
#define PIOS_INCLUDE_SETTINGS
|
||||
#define PIOS_INCLUDE_FLASH
|
||||
/* A really shitty setting saving implementation */
|
||||
//#define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS
|
||||
//#define PIOS_INCLUDE_FLASH_LOGFS_SETTINGS
|
||||
|
||||
/* Other Interfaces */
|
||||
//#define PIOS_INCLUDE_I2C_ESC
|
||||
|
@ -74,6 +74,8 @@ uint32_t pios_com_telem_usb_id = 0;
|
||||
uint32_t pios_com_telem_rf_id = 0;
|
||||
uint32_t pios_com_bridge_id = 0;
|
||||
|
||||
uintptr_t pios_uavo_settings_fs_id;
|
||||
|
||||
/*
|
||||
* Setup a com port based on the passed cfg, driver and buffer sizes. tx size of -1 make the port rx only
|
||||
*/
|
||||
|
3
flight/tests/logfs/FreeRTOS.h
Normal file
3
flight/tests/logfs/FreeRTOS.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <stdlib.h>
|
||||
#define pvPortMalloc(xSize) (malloc(xSize))
|
||||
#define vPortFree(pv) (free(pv))
|
@ -1,9 +1,14 @@
|
||||
#ifndef PIOS_H
|
||||
#define PIOS_H
|
||||
|
||||
/* PIOS board specific feature selection */
|
||||
/* PIOS Feature Selection */
|
||||
#include "pios_config.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
/* FreeRTOS Includes */
|
||||
#include "FreeRTOS.h"
|
||||
#endif
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH
|
||||
#include <pios_flash.h>
|
||||
#include <pios_flashfs.h>
|
||||
|
@ -3,5 +3,7 @@
|
||||
|
||||
/* Enable/Disable PiOS modules */
|
||||
#define PIOS_INCLUDE_FLASH
|
||||
//#define PIOS_FLASHFS_LOGFS_MAX_DEVS 5
|
||||
#define PIOS_INCLUDE_FREERTOS
|
||||
|
||||
#endif /* PIOS_CONFIG_H */
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <stdio.h> /* fopen/fread/fwrite/fseek */
|
||||
#include <assert.h> /* assert */
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include "pios_flash_ut_priv.h"
|
||||
|
||||
@ -55,6 +55,25 @@ int32_t PIOS_Flash_UT_Init(uintptr_t * flash_id, const struct pios_flash_ut_cfg
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t PIOS_Flash_UT_Destroy(uintptr_t flash_id) {
|
||||
/* Check inputs */
|
||||
assert(flash_id);
|
||||
struct flash_ut_dev * flash_dev = (void*)flash_id;
|
||||
|
||||
if (flash_dev->flash_file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(flash_dev->flash_file);
|
||||
|
||||
free(flash_dev);
|
||||
|
||||
unlink (FLASH_IMAGE_FILE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
*
|
||||
* Provide a PIOS flash driver API
|
||||
|
@ -7,6 +7,7 @@ struct pios_flash_ut_cfg {
|
||||
|
||||
int32_t PIOS_Flash_UT_Init(uintptr_t * flash_id, const struct pios_flash_ut_cfg * cfg);
|
||||
|
||||
int32_t PIOS_Flash_UT_Destroy(uintptr_t flash_id);
|
||||
extern const struct pios_flash_driver pios_ut_flash_driver;
|
||||
|
||||
#if !defined(FLASH_IMAGE_FILE)
|
||||
|
@ -13,7 +13,8 @@ extern struct pios_flash_ut_cfg flash_config;
|
||||
|
||||
#include "pios_flashfs_logfs_priv.h"
|
||||
|
||||
extern struct flashfs_logfs_cfg flashfs_config;
|
||||
extern struct flashfs_logfs_cfg flashfs_config_partition_a;
|
||||
extern struct flashfs_logfs_cfg flashfs_config_partition_b;
|
||||
|
||||
#include "pios_flashfs.h" /* PIOS_FLASHFS_* */
|
||||
|
||||
@ -30,6 +31,9 @@ extern struct flashfs_logfs_cfg flashfs_config;
|
||||
#define OBJ3_ID 0x99999999
|
||||
#define OBJ3_SIZE (256 - 12) // leave room for the slot header
|
||||
|
||||
#define OBJ4_ID 0x90901111
|
||||
#define OBJ4_SIZE (768) // only fits in partition b slots
|
||||
|
||||
// To use a test fixture, derive a class from testing::Test.
|
||||
class LogfsTestRaw : public testing::Test {
|
||||
protected:
|
||||
@ -62,6 +66,11 @@ protected:
|
||||
for (uint32_t i = 0; i < sizeof(obj3); i++) {
|
||||
obj3[i] = 0x30 + (i % 10);
|
||||
}
|
||||
|
||||
/* Set up obj4 */
|
||||
for (uint32_t i = 0; i < sizeof(obj4); i++) {
|
||||
obj4[i] = 0x40 + (i % 10);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
@ -72,11 +81,13 @@ protected:
|
||||
unsigned char obj1_alt[OBJ1_SIZE];
|
||||
unsigned char obj2[OBJ2_SIZE];
|
||||
unsigned char obj3[OBJ3_SIZE];
|
||||
unsigned char obj4[OBJ4_SIZE];
|
||||
};
|
||||
|
||||
TEST_F(LogfsTestRaw, FlashInit) {
|
||||
uintptr_t flash_id;
|
||||
EXPECT_EQ(0, PIOS_Flash_UT_Init(&flash_id, &flash_config));
|
||||
PIOS_Flash_UT_Destroy(flash_id);
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestRaw, LogfsInit) {
|
||||
@ -84,7 +95,9 @@ TEST_F(LogfsTestRaw, LogfsInit) {
|
||||
EXPECT_EQ(0, PIOS_Flash_UT_Init(&flash_id, &flash_config));
|
||||
|
||||
uintptr_t fs_id;
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config, &pios_ut_flash_driver, flash_id));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config_partition_a, &pios_ut_flash_driver, flash_id));
|
||||
PIOS_FLASHFS_Logfs_Destroy(fs_id);
|
||||
PIOS_Flash_UT_Destroy(flash_id);
|
||||
}
|
||||
|
||||
class LogfsTestCooked : public LogfsTestRaw {
|
||||
@ -94,14 +107,33 @@ protected:
|
||||
LogfsTestRaw::SetUp();
|
||||
|
||||
/* Init the flash and the flashfs so we don't need to repeat this in every test */
|
||||
uintptr_t flash_id;
|
||||
EXPECT_EQ(0, PIOS_Flash_UT_Init(&flash_id, &flash_config));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config, &pios_ut_flash_driver, flash_id));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config_partition_a, &pios_ut_flash_driver, flash_id));
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
PIOS_FLASHFS_Logfs_Destroy(fs_id);
|
||||
PIOS_Flash_UT_Destroy(flash_id);
|
||||
}
|
||||
|
||||
uintptr_t flash_id;
|
||||
uintptr_t fs_id;
|
||||
};
|
||||
|
||||
TEST_F(LogfsTestCooked, BadIdLogfsFormat) {
|
||||
EXPECT_EQ(-1, PIOS_FLASHFS_Format(fs_id + 1));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCooked, BadIdSave) {
|
||||
EXPECT_EQ(-1, PIOS_FLASHFS_ObjSave(fs_id + 1, OBJ1_ID, 0, obj1, sizeof(obj1)));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCooked, BadIdLoad) {
|
||||
unsigned char obj1_check[OBJ1_SIZE];
|
||||
memset(obj1_check, 0, sizeof(obj1_check));
|
||||
EXPECT_EQ(-1, PIOS_FLASHFS_ObjLoad(fs_id + 1, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCooked, LogfsFormat) {
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_Format(fs_id));
|
||||
}
|
||||
@ -129,7 +161,7 @@ TEST_F(LogfsTestCooked, WriteVerifyDeleteVerifyOne) {
|
||||
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjDelete(fs_id, OBJ1_ID, 0));
|
||||
|
||||
EXPECT_EQ(-2, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)));
|
||||
EXPECT_EQ(-3, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCooked, WriteTwoVerifyOneA) {
|
||||
@ -170,7 +202,7 @@ TEST_F(LogfsTestCooked, WriteVerifyZeroLength) {
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCooked, WriteMaxSize) {
|
||||
/* Write a zero length object */
|
||||
/* Write a max length object */
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ3_ID, 0, obj3, sizeof(obj3)));
|
||||
}
|
||||
|
||||
@ -178,7 +210,7 @@ TEST_F(LogfsTestCooked, ReadNonexistent) {
|
||||
/* Read back a zero length object -- basically an existence check */
|
||||
unsigned char obj1_check[OBJ1_SIZE];
|
||||
memset(obj1_check, 0, sizeof(obj1_check));
|
||||
EXPECT_EQ(-2, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)));
|
||||
EXPECT_EQ(-3, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCooked, WriteVerifyMultiInstance) {
|
||||
@ -203,12 +235,12 @@ TEST_F(LogfsTestCooked, WriteVerifyMultiInstance) {
|
||||
|
||||
TEST_F(LogfsTestCooked, FillFilesystemAndGarbageCollect) {
|
||||
/* Fill up the entire filesystem with multiple instances of obj1 */
|
||||
for (uint32_t i = 0; i < (flashfs_config.arena_size / flashfs_config.slot_size) - 1; i++) {
|
||||
for (uint32_t i = 0; i < (flashfs_config_partition_a.arena_size / flashfs_config_partition_a.slot_size) - 1; i++) {
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, i, obj1, sizeof(obj1)));
|
||||
}
|
||||
|
||||
/* Should fail to add a new object since the filesystem is full */
|
||||
EXPECT_EQ(-3, PIOS_FLASHFS_ObjSave(fs_id, OBJ2_ID, 0, obj2, sizeof(obj2)));
|
||||
EXPECT_EQ(-4, PIOS_FLASHFS_ObjSave(fs_id, OBJ2_ID, 0, obj2, sizeof(obj2)));
|
||||
|
||||
/* Now save a new version of an existing object which should trigger gc and succeed */
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1_alt, sizeof(obj1_alt)));
|
||||
@ -257,3 +289,97 @@ TEST_F(LogfsTestCooked, WriteManyVerify) {
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ3_ID, 0, obj3_check, sizeof(obj3_check)));
|
||||
EXPECT_EQ(0, memcmp(obj3, obj3_check, sizeof(obj3)));
|
||||
}
|
||||
|
||||
class LogfsTestCookedMultiPart : public LogfsTestRaw {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
/* First, we need to set up the super fixture (LogfsTestRaw) */
|
||||
LogfsTestRaw::SetUp();
|
||||
|
||||
/* Init the flash and the flashfs so we don't need to repeat this in every test */
|
||||
EXPECT_EQ(0, PIOS_Flash_UT_Init(&flash_id, &flash_config));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_Logfs_Init(&fs_id_a, &flashfs_config_partition_a, &pios_ut_flash_driver, flash_id));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_Logfs_Init(&fs_id_b, &flashfs_config_partition_b, &pios_ut_flash_driver, flash_id));
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
PIOS_FLASHFS_Logfs_Destroy(fs_id_b);
|
||||
PIOS_FLASHFS_Logfs_Destroy(fs_id_a);
|
||||
PIOS_Flash_UT_Destroy(flash_id);
|
||||
}
|
||||
|
||||
uintptr_t flash_id;
|
||||
uintptr_t fs_id_a;
|
||||
uintptr_t fs_id_b;
|
||||
};
|
||||
|
||||
TEST_F(LogfsTestCookedMultiPart, WriteOneWriteOneVerify) {
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_a, OBJ1_ID, 0, obj1, sizeof(obj1)));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_b, OBJ2_ID, 0, obj2, sizeof(obj2)));
|
||||
|
||||
/* OBJ1 found in A */
|
||||
unsigned char obj1_check[OBJ1_SIZE];
|
||||
memset(obj1_check, 0, sizeof(obj1_check));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id_a, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)));
|
||||
EXPECT_EQ(0, memcmp(obj1, obj1_check, sizeof(obj1)));
|
||||
|
||||
/* OBJ2 found in B */
|
||||
unsigned char obj2_check[OBJ2_SIZE];
|
||||
memset(obj2_check, 0, sizeof(obj2_check));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id_b, OBJ2_ID, 0, obj2_check, sizeof(obj2_check)));
|
||||
EXPECT_EQ(0, memcmp(obj2, obj2_check, sizeof(obj2)));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCookedMultiPart, WriteOneWriteOneFormatOneVerify) {
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_a, OBJ1_ID, 0, obj1, sizeof(obj1)));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_b, OBJ2_ID, 0, obj2, sizeof(obj2)));
|
||||
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_Format(fs_id_a));
|
||||
|
||||
/* OBJ2 still found in B */
|
||||
unsigned char obj2_check[OBJ2_SIZE];
|
||||
memset(obj2_check, 0, sizeof(obj2_check));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id_b, OBJ2_ID, 0, obj2_check, sizeof(obj2_check)));
|
||||
EXPECT_EQ(0, memcmp(obj2, obj2_check, sizeof(obj2)));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCookedMultiPart, WriteOneWriteOneNoCross) {
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_a, OBJ1_ID, 0, obj1, sizeof(obj1)));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_b, OBJ2_ID, 0, obj2, sizeof(obj2)));
|
||||
|
||||
/* OBJ1 not found in B */
|
||||
unsigned char obj1_check[OBJ1_SIZE];
|
||||
memset(obj1_check, 0, sizeof(obj1_check));
|
||||
EXPECT_EQ(-3, PIOS_FLASHFS_ObjLoad(fs_id_b, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)));
|
||||
|
||||
/* OBJ2 not found in A */
|
||||
unsigned char obj2_check[OBJ2_SIZE];
|
||||
memset(obj2_check, 0, sizeof(obj2_check));
|
||||
EXPECT_EQ(-3, PIOS_FLASHFS_ObjLoad(fs_id_a, OBJ2_ID, 0, obj2_check, sizeof(obj2_check)));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCookedMultiPart, WriteOneWriteOneDeleteOne) {
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_a, OBJ1_ID, 0, obj1, sizeof(obj1)));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_b, OBJ2_ID, 0, obj2, sizeof(obj2)));
|
||||
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjDelete(fs_id_a, OBJ1_ID, 0));
|
||||
|
||||
/* OBJ1 not found in A */
|
||||
unsigned char obj1_check[OBJ1_SIZE];
|
||||
memset(obj1_check, 0, sizeof(obj1_check));
|
||||
EXPECT_EQ(-3, PIOS_FLASHFS_ObjLoad(fs_id_a, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)));
|
||||
|
||||
/* OBJ2 still found in B */
|
||||
unsigned char obj2_check[OBJ2_SIZE];
|
||||
memset(obj2_check, 0, sizeof(obj2_check));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id_b, OBJ2_ID, 0, obj2_check, sizeof(obj2_check)));
|
||||
}
|
||||
|
||||
TEST_F(LogfsTestCookedMultiPart, WriteLarge) {
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id_b, OBJ4_ID, 0, obj4, sizeof(obj4)));
|
||||
|
||||
/* OBJ4 found in B */
|
||||
unsigned char obj4_check[OBJ4_SIZE];
|
||||
memset(obj4_check, 0, sizeof(obj4_check));
|
||||
EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id_b, OBJ4_ID, 0, obj4_check, sizeof(obj4_check)));
|
||||
}
|
||||
|
@ -7,15 +7,15 @@
|
||||
|
||||
|
||||
const struct pios_flash_ut_cfg flash_config = {
|
||||
.size_of_flash = 0x00200000,
|
||||
.size_of_flash = 0x00300000,
|
||||
.size_of_sector = 0x00010000,
|
||||
};
|
||||
|
||||
#include "pios_flashfs_logfs_priv.h"
|
||||
|
||||
const struct flashfs_logfs_cfg flashfs_config = {
|
||||
const struct flashfs_logfs_cfg flashfs_config_partition_a = {
|
||||
.fs_magic = 0x89abceef,
|
||||
.total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */
|
||||
.total_fs_size = 0x00200000, /* 2M bytes (32 sectors) */
|
||||
.arena_size = 0x00010000, /* 256 * slot size */
|
||||
.slot_size = 0x00000100, /* 256 bytes */
|
||||
|
||||
@ -24,3 +24,14 @@ const struct flashfs_logfs_cfg flashfs_config = {
|
||||
.page_size = 0x00000100, /* 256 bytes */
|
||||
};
|
||||
|
||||
const struct flashfs_logfs_cfg flashfs_config_partition_b = {
|
||||
.fs_magic = 0x89abceef,
|
||||
.total_fs_size = 0x00100000, /* 1M bytes (16 sectors) */
|
||||
.arena_size = 0x00010000, /* 64 * slot size */
|
||||
.slot_size = 0x00000400, /* 256 bytes */
|
||||
|
||||
.start_offset = 0x00200000, /* start after partition a */
|
||||
.sector_size = 0x00010000, /* 64K bytes */
|
||||
.page_size = 0x00000100, /* 256 bytes */
|
||||
};
|
||||
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "openpilot.h"
|
||||
#include "pios_struct_helper.h"
|
||||
|
||||
extern uintptr_t pios_uavo_settings_fs_id;
|
||||
|
||||
#if (defined(__MACH__) && defined(__APPLE__))
|
||||
#include <mach-o/getsect.h>
|
||||
#endif
|
||||
@ -182,8 +184,8 @@ static int32_t connectObj(UAVObjHandle obj_handle, xQueueHandle queue,
|
||||
static int32_t disconnectObj(UAVObjHandle obj_handle, xQueueHandle queue,
|
||||
UAVObjEventCallback cb);
|
||||
|
||||
#if defined(PIOS_USE_SETTINGS_ON_SDCARD) && defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS)
|
||||
#error Both PIOS_USE_SETTINGS_ON_SDCARD and PIOS_INCLUDE_FLASH_SECTOR_SETTINGS. Only one settings storage allowed.
|
||||
#if defined(PIOS_USE_SETTINGS_ON_SDCARD) && defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
|
||||
#error Both PIOS_USE_SETTINGS_ON_SDCARD and PIOS_INCLUDE_FLASH_LOGFS_SETTINGS. Only one settings storage allowed.
|
||||
#endif
|
||||
|
||||
#if defined(PIOS_USE_SETTINGS_ON_SDCARD)
|
||||
@ -792,12 +794,12 @@ int32_t UAVObjSave(UAVObjHandle obj_handle, __attribute__((unused)) uint16_t ins
|
||||
{
|
||||
PIOS_Assert(obj_handle);
|
||||
|
||||
#if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS)
|
||||
#if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
|
||||
if (UAVObjIsMetaobject(obj_handle)) {
|
||||
if (instId != 0)
|
||||
return -1;
|
||||
|
||||
if (PIOS_FLASHFS_ObjSave(0, UAVObjGetID(obj_handle), instId, (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle), UAVObjGetNumBytes(obj_handle)) != 0)
|
||||
if (PIOS_FLASHFS_ObjSave(pios_uavo_settings_fs_id, UAVObjGetID(obj_handle), instId, (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle), UAVObjGetNumBytes(obj_handle)) != 0)
|
||||
return -1;
|
||||
} else {
|
||||
InstanceHandle instEntry = getInstance( (struct UAVOData *)obj_handle, instId);
|
||||
@ -808,7 +810,7 @@ int32_t UAVObjSave(UAVObjHandle obj_handle, __attribute__((unused)) uint16_t ins
|
||||
if (InstanceData(instEntry) == NULL)
|
||||
return -1;
|
||||
|
||||
if (PIOS_FLASHFS_ObjSave(0, UAVObjGetID(obj_handle), instId, InstanceData(instEntry), UAVObjGetNumBytes(obj_handle)) != 0)
|
||||
if (PIOS_FLASHFS_ObjSave(pios_uavo_settings_fs_id, UAVObjGetID(obj_handle), instId, InstanceData(instEntry), UAVObjGetNumBytes(obj_handle)) != 0)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@ -946,13 +948,13 @@ int32_t UAVObjLoad(UAVObjHandle obj_handle, __attribute__((unused)) uint16_t ins
|
||||
{
|
||||
PIOS_Assert(obj_handle);
|
||||
|
||||
#if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS)
|
||||
#if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
|
||||
if (UAVObjIsMetaobject(obj_handle)) {
|
||||
if (instId != 0)
|
||||
return -1;
|
||||
|
||||
// Fire event on success
|
||||
if (PIOS_FLASHFS_ObjLoad(0, UAVObjGetID(obj_handle), instId, (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle), UAVObjGetNumBytes(obj_handle)) == 0)
|
||||
if (PIOS_FLASHFS_ObjLoad(pios_uavo_settings_fs_id, UAVObjGetID(obj_handle), instId, (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle), UAVObjGetNumBytes(obj_handle)) == 0)
|
||||
sendEvent((struct UAVOBase*)obj_handle, instId, EV_UNPACKED);
|
||||
else
|
||||
return -1;
|
||||
@ -964,7 +966,7 @@ int32_t UAVObjLoad(UAVObjHandle obj_handle, __attribute__((unused)) uint16_t ins
|
||||
return -1;
|
||||
|
||||
// Fire event on success
|
||||
if (PIOS_FLASHFS_ObjLoad(0, UAVObjGetID(obj_handle), instId, InstanceData(instEntry), UAVObjGetNumBytes(obj_handle)) == 0)
|
||||
if (PIOS_FLASHFS_ObjLoad(pios_uavo_settings_fs_id, UAVObjGetID(obj_handle), instId, InstanceData(instEntry), UAVObjGetNumBytes(obj_handle)) == 0)
|
||||
sendEvent((struct UAVOBase*)obj_handle, instId, EV_UNPACKED);
|
||||
else
|
||||
return -1;
|
||||
@ -1021,8 +1023,8 @@ int32_t UAVObjLoad(UAVObjHandle obj_handle, __attribute__((unused)) uint16_t ins
|
||||
int32_t UAVObjDelete(UAVObjHandle obj_handle, __attribute__((unused)) uint16_t instId)
|
||||
{
|
||||
PIOS_Assert(obj_handle);
|
||||
#if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS)
|
||||
PIOS_FLASHFS_ObjDelete(0, UAVObjGetID(obj_handle), instId);
|
||||
#if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
|
||||
PIOS_FLASHFS_ObjDelete(pios_uavo_settings_fs_id, UAVObjGetID(obj_handle), instId);
|
||||
#endif
|
||||
#if defined(PIOS_USE_SETTINGS_ON_SDCARD)
|
||||
uint8_t filename[14];
|
||||
|
@ -137,7 +137,10 @@ BOARD_CDEFS += -DFW_DESC_SIZE=$(FW_DESC_SIZE)
|
||||
BOARD_CDEFS += -DBL_BANK_BASE=$(BL_BANK_BASE)
|
||||
BOARD_CDEFS += -DBL_BANK_SIZE=$(BL_BANK_SIZE)
|
||||
BOARD_CDEFS += -DBL_DESC_SIZE=$(BL_DESC_SIZE)
|
||||
|
||||
ifdef EE_BANK_BASE
|
||||
BOARD_CDEFS += -DEE_BANK_BASE=$(EE_BANK_BASE)
|
||||
BOARD_CDEFS += -DEE_BANK_SIZE=$(EE_BANK_SIZE)
|
||||
endif
|
||||
CDEFS += $(BOARD_CDEFS)
|
||||
|
||||
ifeq ($(DEBUG), YES)
|
||||
|
Loading…
x
Reference in New Issue
Block a user