mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-20 10:54:14 +01:00
Merge branch 'next' ...
This commit is contained in:
commit
f630351c75
@ -472,40 +472,40 @@ 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;
|
||||
|
@ -319,7 +319,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;
|
||||
|
@ -32,15 +32,20 @@
|
||||
#include <stdbool.h>
|
||||
#include <openpilot.h>
|
||||
#include <pios_math.h>
|
||||
|
||||
#include <pios_wdg.h>
|
||||
#include "pios_flashfs_logfs_priv.h"
|
||||
|
||||
/*
|
||||
* Filesystem state data tracked in RAM
|
||||
*/
|
||||
|
||||
enum pios_flashfs_logfs_dev_magic {
|
||||
PIOS_FLASHFS_LOGFS_DEV_MAGIC = 0x94938201,
|
||||
};
|
||||
|
||||
struct logfs_state {
|
||||
const struct flashfs_logfs_cfg *cfg;
|
||||
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,30 +115,30 @@ 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,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
@ -149,17 +152,17 @@ 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,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (arena_hdr.state != ARENA_STATE_ERASED) {
|
||||
@ -171,10 +174,10 @@ 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,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
@ -187,15 +190,18 @@ 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
|
||||
PIOS_LED_Toggle(PIOS_LED_HEARTBEAT);
|
||||
#endif
|
||||
if (logfs_erase_arena(arena) != 0) {
|
||||
#ifdef PIOS_INCLUDE_WDG
|
||||
PIOS_WDG_Clear();
|
||||
#endif
|
||||
if (logfs_erase_arena(logfs, arena) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -209,17 +215,17 @@ 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,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
/* Failed to read arena header */
|
||||
return -1;
|
||||
}
|
||||
@ -231,10 +237,10 @@ 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,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
@ -248,19 +254,19 @@ 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,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
/* Failed to read arena header */
|
||||
return -1;
|
||||
}
|
||||
@ -272,10 +278,10 @@ 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,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
@ -290,26 +296,29 @@ 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,
|
||||
arena_addr,
|
||||
(uint8_t *)&arena_hdr,
|
||||
sizeof(arena_hdr)) != 0) {
|
||||
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;
|
||||
}
|
||||
#ifdef PIOS_INCLUDE_WDG
|
||||
PIOS_WDG_Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Didn't find an active arena */
|
||||
@ -345,7 +354,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];
|
||||
@ -361,19 +370,19 @@ static int32_t logfs_raw_copy_bytes(uintptr_t src_addr, uint16_t src_size, uintp
|
||||
}
|
||||
|
||||
/* Read a block of data from source */
|
||||
if (logfs.driver->read_data(logfs.flash_id,
|
||||
src_addr,
|
||||
data_block,
|
||||
blk_size) != 0) {
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
src_addr,
|
||||
data_block,
|
||||
blk_size) != 0) {
|
||||
/* Failed to read next chunk from source */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write a block of data to destination */
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
dst_addr,
|
||||
data_block,
|
||||
blk_size) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
dst_addr,
|
||||
data_block,
|
||||
blk_size) != 0) {
|
||||
/* Failed to write chunk to destination */
|
||||
return -2;
|
||||
}
|
||||
@ -392,9 +401,9 @@ static int32_t logfs_raw_copy_bytes(uintptr_t src_addr, uint16_t src_size, uintp
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -402,40 +411,40 @@ 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,
|
||||
slot_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof(slot_hdr)) != 0) {
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -444,14 +453,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:
|
||||
@ -460,12 +469,61 @@ 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 /* if defined(PIOS_INCLUDE_FREERTOS) */
|
||||
|
||||
/**
|
||||
* @brief Initialize the flash object setting FS
|
||||
* @return 0 if success, -1 if failure
|
||||
@ -486,15 +544,23 @@ int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t *fs_id, const struct flashfs_logfs_cfg
|
||||
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;
|
||||
}
|
||||
@ -503,17 +569,17 @@ int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t *fs_id, const struct flashfs_logfs_cfg
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -526,7 +592,7 @@ int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t *fs_id, const struct flashfs_logfs_cfg
|
||||
}
|
||||
|
||||
/* 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;
|
||||
@ -535,33 +601,51 @@ int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t *fs_id, const struct flashfs_logfs_cfg
|
||||
/* 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)
|
||||
static int32_t logfs_garbage_collect(struct logfs_state *logfs)
|
||||
{
|
||||
PIOS_Assert(logfs.mounted);
|
||||
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;
|
||||
}
|
||||
@ -569,20 +653,21 @@ 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,
|
||||
src_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof(slot_hdr)) != 0) {
|
||||
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) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
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 */
|
||||
@ -590,25 +675,28 @@ static int32_t logfs_garbage_collect(void)
|
||||
}
|
||||
dst_slot_id++;
|
||||
}
|
||||
#ifdef PIOS_INCLUDE_WDG
|
||||
PIOS_WDG_Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -616,7 +704,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);
|
||||
@ -627,14 +715,14 @@ static int16_t logfs_object_find_next(struct slot_header *slot_hdr, uint16_t *cu
|
||||
}
|
||||
|
||||
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,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof(*slot_hdr)) != 0) {
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof(*slot_hdr)) != 0) {
|
||||
return -2;
|
||||
}
|
||||
if (slot_hdr->state == SLOT_STATE_EMPTY) {
|
||||
@ -648,6 +736,9 @@ static int16_t logfs_object_find_next(struct slot_header *slot_hdr, uint16_t *cu
|
||||
*curr_slot = slot_id;
|
||||
return 0;
|
||||
}
|
||||
#ifdef PIOS_INCLUDE_WDG
|
||||
PIOS_WDG_Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* No matching entry was found */
|
||||
@ -656,7 +747,7 @@ static int16_t logfs_object_find_next(struct slot_header *slot_hdr, uint16_t *cu
|
||||
|
||||
/* 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;
|
||||
|
||||
@ -665,21 +756,21 @@ static int8_t logfs_delete_object(uint32_t obj_id, uint16_t obj_inst_id)
|
||||
|
||||
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,
|
||||
slot_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof(slot_hdr)) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof(slot_hdr)) != 0) {
|
||||
rc = -2;
|
||||
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 */
|
||||
@ -698,30 +789,30 @@ 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,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof(*slot_hdr)) != 0) {
|
||||
if (logfs->driver->read_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof(*slot_hdr)) != 0) {
|
||||
/* Failed to read slot header for candidate slot */
|
||||
return -3;
|
||||
}
|
||||
@ -738,46 +829,46 @@ static int8_t logfs_reserve_free_slot(uint16_t *slot_id, struct slot_header *slo
|
||||
slot_hdr->obj_inst_id = obj_inst_id;
|
||||
slot_hdr->obj_size = obj_size;
|
||||
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof(*slot_hdr)) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)slot_hdr,
|
||||
sizeof(*slot_hdr)) != 0) {
|
||||
/* Failed to write the slot header */
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
slot_addr + slot_offset,
|
||||
obj_data,
|
||||
write_size) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
slot_addr + slot_offset,
|
||||
obj_data,
|
||||
write_size) != 0) {
|
||||
/* Failed to write the object data to the slot */
|
||||
return -2;
|
||||
}
|
||||
@ -790,16 +881,16 @@ static int8_t logfs_append_to_log(uint32_t obj_id, uint16_t obj_inst_id, uint8_t
|
||||
|
||||
/* Mark this slot active in one atomic step */
|
||||
slot_hdr.state = SLOT_STATE_ACTIVE;
|
||||
if (logfs.driver->write_data(logfs.flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof(slot_hdr)) != 0) {
|
||||
if (logfs->driver->write_data(logfs->flash_id,
|
||||
slot_addr,
|
||||
(uint8_t *)&slot_hdr,
|
||||
sizeof(slot_hdr)) != 0) {
|
||||
/* Failed to mark the slot active */
|
||||
return -4;
|
||||
}
|
||||
|
||||
/* Object has been successfully written to the slot */
|
||||
logfs.num_active_slots++;
|
||||
logfs->num_active_slots++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -819,26 +910,34 @@ static int8_t logfs_append_to_log(uint32_t obj_id, uint16_t obj_inst_id, uint8_t
|
||||
* @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;
|
||||
}
|
||||
|
||||
@ -848,36 +947,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;
|
||||
}
|
||||
|
||||
@ -885,7 +984,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;
|
||||
@ -899,47 +998,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,
|
||||
slot_addr + sizeof(slot_hdr),
|
||||
(uint8_t *)obj_data,
|
||||
obj_size) != 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -948,7 +1055,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;
|
||||
@ -960,20 +1067,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;
|
||||
}
|
||||
|
||||
@ -981,7 +1096,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;
|
||||
@ -991,46 +1106,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
|
||||
}
|
||||
|
304
flight/pios/stm32f10x/pios_flash_internal.c
Normal file
304
flight/pios/stm32f10x/pios_flash_internal.c
Normal file
@ -0,0 +1,304 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @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 */
|
@ -287,16 +287,21 @@ 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;
|
||||
|
@ -167,6 +167,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;
|
||||
@ -204,7 +205,7 @@ void PIOS_Board_Init(void)
|
||||
if (PIOS_IAP_ReadBootCmd(0) == PIOS_IAP_CLEAR_FLASH_CMD_0 &&
|
||||
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
|
||||
|
||||
|
@ -98,6 +98,28 @@ 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,16 +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 /* if defined(PIOS_INCLUDE_FLASH_EEPROM) */
|
||||
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 */
|
||||
|
||||
|
@ -104,6 +104,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.
|
||||
@ -161,11 +163,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
|
||||
|
@ -675,8 +675,9 @@ const struct pios_rfm22b_cfg *PIOS_BOARD_HW_DEFS_GetRfm22Cfg(uint32_t board_revi
|
||||
#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 */
|
||||
@ -687,6 +688,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 */
|
||||
|
||||
|
@ -234,6 +234,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
|
||||
*/
|
||||
@ -350,16 +353,26 @@ 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)) {
|
||||
if (PIOS_FLASHFS_Logfs_Init(&pios_user_fs_id, &flashfs_external_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* if defined(PIOS_INCLUDE_FLASH) */
|
||||
|
||||
#if defined(PIOS_INCLUDE_RTC)
|
||||
PIOS_RTC_Init(&pios_rtc_main_cfg);
|
||||
@ -370,12 +383,12 @@ void PIOS_Board_Init(void)
|
||||
if (PIOS_IAP_ReadBootCmd(0) == PIOS_IAP_CLEAR_FLASH_CMD_0 &&
|
||||
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);
|
||||
}
|
||||
|
||||
PIOS_WDG_Init();
|
||||
/* Initialize UAVObject libraries */
|
||||
EventDispatcherInitialize();
|
||||
UAVObjInitialize();
|
||||
|
@ -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
|
||||
|
@ -455,18 +455,33 @@ 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 = {
|
||||
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 */
|
||||
.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 */
|
||||
|
||||
#if defined(PIOS_OVERO_SPI)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -304,6 +304,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
|
||||
*/
|
||||
@ -376,6 +380,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);
|
||||
@ -390,20 +406,18 @@ 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)) {
|
||||
if (PIOS_FLASHFS_Logfs_Init(&pios_user_fs_id, &flashfs_external_cfg, &pios_jedec_flash_driver, flash_id)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
@ -417,7 +431,7 @@ void PIOS_Board_Init(void)
|
||||
if (PIOS_IAP_ReadBootCmd(0) == PIOS_IAP_CLEAR_FLASH_CMD_0 &&
|
||||
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
|
||||
*/
|
||||
|
@ -42,7 +42,8 @@ FWINFO_BIN = $(FW_BIN).firmware_info.bin
|
||||
|
||||
$(OUTDIR)/$(TARGET).bin: $(BL_BIN) $(FW_BIN)
|
||||
$(V0) @$(ECHO) $(MSG_FLASH_IMG) $@
|
||||
$(V1) $(ENTIRE_FLASH) $(EF_VERBOSE) \
|
||||
$(V1) $(ENTIRE_FLASH) \
|
||||
$(EF_VERBOSE) \
|
||||
--bl-bank-base=$(BL_BANK_BASE) \
|
||||
--bl-bank-size=$(BL_BANK_SIZE) \
|
||||
--fw-bank-base=$(FW_BANK_BASE) \
|
||||
|
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,26 @@ 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)
|
||||
|
@ -12,7 +12,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_* */
|
||||
}
|
||||
@ -28,6 +29,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()
|
||||
@ -73,12 +82,14 @@ 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) {
|
||||
@ -87,7 +98,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 {
|
||||
@ -98,15 +111,35 @@ 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));
|
||||
}
|
||||
@ -134,7 +167,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) {
|
||||
@ -175,7 +208,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)));
|
||||
}
|
||||
|
||||
@ -184,7 +217,7 @@ TEST_F(LogfsTestCooked, ReadNonexistent) {
|
||||
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) {
|
||||
@ -209,12 +242,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)));
|
||||
@ -263,3 +296,99 @@ 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 */
|
||||
|
||||
@ -23,3 +23,14 @@ const struct flashfs_logfs_cfg flashfs_config = {
|
||||
.sector_size = 0x00010000, /* 64K bytes */
|
||||
.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)
|
||||
@ -802,13 +804,13 @@ 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 {
|
||||
@ -822,11 +824,11 @@ int32_t UAVObjSave(UAVObjHandle obj_handle, __attribute__((unused)) uint16_t ins
|
||||
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 /* if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS) */
|
||||
#endif /* if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS) */
|
||||
#if defined(PIOS_USE_SETTINGS_ON_SDCARD)
|
||||
FILEINFO file;
|
||||
uint8_t filename[14];
|
||||
@ -959,14 +961,14 @@ 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;
|
||||
@ -979,14 +981,14 @@ int32_t UAVObjLoad(UAVObjHandle obj_handle, __attribute__((unused)) uint16_t ins
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS) */
|
||||
#endif /* if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS) */
|
||||
|
||||
#if defined(PIOS_USE_SETTINGS_ON_SDCARD)
|
||||
FILEINFO file;
|
||||
@ -1037,8 +1039,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];
|
||||
|
@ -79,7 +79,7 @@
|
||||
}
|
||||
// This tab is for the authors/contributors/credits
|
||||
Rectangle {
|
||||
property string title: "Authors"
|
||||
property string title: "Contributors"
|
||||
anchors.fill: parent; color: "#e3e3e3"
|
||||
Rectangle {
|
||||
anchors.fill: parent; anchors.margins: 20
|
||||
|
@ -62,6 +62,8 @@ ListModel {
|
||||
ListElement{ name:"Sami Korhonen" }
|
||||
|
||||
ListElement{ name:"Thorsten Klose" }
|
||||
|
||||
ListElement{ name:"Rick King" }
|
||||
|
||||
ListElement{ name:"Hallvard Kristiansen" }
|
||||
|
||||
@ -92,6 +94,8 @@ ListModel {
|
||||
ListElement{ name:"Cathy Moss" }
|
||||
|
||||
ListElement{ name:"Angus Peart" }
|
||||
|
||||
ListElement{ name:"John Pike" }
|
||||
|
||||
ListElement{ name:"Dmytro Poplavskiy" }
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">OpenPilot CopterControl sensor calibration procedure</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">OpenPilot sensor calibration procedure</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; font-weight:600;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The wizard needs to get information from the controller to determine in which position the vehicle is normally considered to be level. To be able to successfully perform these measurements, you need to place the vehicle on a surface that is as flat and level as possible. Examples of such surfaces could be a table top or the floor. Be careful to ensure that the vehicle really is level, since this step will affect the accelerometer and gyro bias in the controller software.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
|
@ -41,7 +41,7 @@ p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Welcome to the OpenPilot Setup Wizard</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">This wizard will guide you through the basic steps required to setup your OpenPilot controller for the first time. You will be asked questions about your platform (multirotor/heli/fixed-wing) which this wizard will use to configure your aircraft for your maiden flight. </span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">This wizard will guide you through the basic steps required to setup your OpenPilot controller for the first time. You will be asked questions about your platform (multirotor/heli/fixed-wing) which this wizard will use to configure your controller for its first flight. </span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">This wizard does not configure all of the advanced settings available in the GCS Configuration. All basic and advanced configuration parameters can be modified later by using the GCS Configuration plugin.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
|
@ -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