Back Port nuttx_v3 FLASH based parameter hooks

This commit is contained in:
David Sidrane
2016-07-13 20:42:05 +02:00
committed by Julian Oes
parent 39ce201efe
commit 5e8d6375c9
9 changed files with 1870 additions and 10 deletions
+2
View File
@@ -56,6 +56,8 @@ if(${OS} STREQUAL "nuttx")
err.c
printload.c
param/param.c
flashparams/flashparams.c
flashparams/flashfs.c
up_cxxinitialize.c
)
elseif ("${CONFIG_SHMEM}" STREQUAL "1")
+3 -1
View File
@@ -456,7 +456,9 @@ bson_encoder_fini(bson_encoder_t encoder)
}
/* sync file */
BSON_FSYNC(encoder->fd);
if (encoder->fd > -1) {
BSON_FSYNC(encoder->fd);
}
return 0;
}
File diff suppressed because it is too large Load Diff
+220
View File
@@ -0,0 +1,220 @@
/****************************************************************************
*
* Copyright (c) 2015 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file param.h
*
* Global flash based parameter store.
*
* This provides the mechanisms to interface to the PX4
* parameter system but replace the IO with non file based flash
* i/o routines. So that the code my be implemented on a SMALL memory
* foot print device.
*
*/
#ifndef _SYSTEMLIB_FLASHPARAMS_NUTTX_PARAM_H
#define _SYSTEMLIB_FLASHPARAMS_NUTTX_PARAM_H
#include <stdint.h>
#include <stdbool.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/*
* PARAMETER_BUFFER_SIZE must be defined larger then the maximum parameter
* memory needed to commit the recored + ~20 bytes. For the syslib's parameter
* this would be the size of the bson representations of the data
*/
#if !defined(PARAMETER_BUFFER_SIZE)
#define PARAMETER_BUFFER_SIZE 512
#endif
__BEGIN_DECLS
/*
* Define the interface data a flash_file_token_t
* is like a file name
*
*/
typedef uint32_t flash_file_tokens_t;
typedef struct flash_file_token_t {
union {
flash_file_tokens_t t;
uint8_t n[sizeof(flash_file_tokens_t)];
};
} flash_file_token_t;
/*
* Define the parameter "file name" Currently there is only
* and it is hard coded. If more are added the
* parameter_flashfs_write would need to support a backing buffer
* for when a sector is erased.
*/
__EXPORT extern const flash_file_token_t parameters_token;
/* Define the elements of the array passed to the
* parameter_flashfs_init function
*
* For example
* static sector_descriptor_t sector_map[] = {
* {1, 16 * 1024, 0x08004000},
* {2, 16 * 1024, 0x08008000},
* {0, 0, 0},
*
*/
typedef struct sector_descriptor_t {
uint8_t page;
uint16_t size;
uint32_t address;
} sector_descriptor_t;
/****************************************************************************
* Name: parameter_flashfs_init
*
* Description:
* This helper function advances the flash entry header pointer to the
* locations of the next entry.
*
* Input Parameters:
* fconfig - A pointer to an null entry terminated array of
* flash_file_sector_t
* buffer - A pointer to a memory to make available to callers
* for write operations. When allocated to the caller
* space is reserved in the front for the
* flash_entry_header_t.
* If this is passes as NULL. The buffer will be
* allocated from the heap on callse to
* parameter_flashfs_alloc and fread on calls calls
* to parameter_flashfs_write
*
* size - The size of the buffer in bytes. Should be be 0 if buffer
* is NULL
*
* Returned value:
* - A pointer to the next file header location
*
*
****************************************************************************/
__EXPORT int parameter_flashfs_init(sector_descriptor_t *fconfig, uint8_t *buffer, uint16_t size);
/****************************************************************************
* Name: parameter_flashfs_read
*
* Description:
* This function returns a pointer to the locations of the data associated
* with the file token. On successful return *buffer will be set to Flash
* location and *buf_size the length of the user data.
*
* Input Parameters:
* token - File Token File to read
* buffer - A pointer to a pointer that will receive the address
* in flash of the data of this "files" data
* buf_size - A pointer to receive the number of bytes in the "file"
*
* Returned value:
* On success number of bytes read or a negative errno value,
*
*
****************************************************************************/
__EXPORT int parameter_flashfs_read(flash_file_token_t ft, uint8_t **buffer, size_t *buf_size);
/****************************************************************************
* Name: parameter_flashfs_write
*
* Description:
* This function writes user data from the buffer allocated with a previous call
* to parameter_flashfs_alloc. flash starting at the given address
*
* Input Parameters:
* token - File Token File to read
* buffer - A pointer to a buffer with buf_size bytes to be written
* to the flash. This buffer must be allocated
* with a previous call to flash_alloc_buffer
* buf_size - Number of bytes to write
*
* Returned value:
* On success the number of bytes written On Error a negative value of errno
* If static buffer was not provided to parameter_flashfs_init the
* buffer will be freed.
*
****************************************************************************/
__EXPORT int parameter_flashfs_write(flash_file_token_t ft, uint8_t *buffer, size_t buf_size);
/****************************************************************************
* Name: parameter_flashfs_erase
*
* Description:
* This function erases the sectors that were passed to parameter_flashfs_init
*
* Input Parameters:
*
* Returned value:
* On success the number of bytes erased
* On Error a negative value of errno
*
****************************************************************************/
__EXPORT int parameter_flashfs_erase(void);
/****************************************************************************
* Name: parameter_flashfs_alloc
*
* Description:
* This function is called to get a buffer to use in a subsequent call
* to parameter_flashfs_write. The address returned is advanced into the
* buffer to reserve space for the flash entry header.
*
* Input Parameters:
* token - File Token File to read (not used)
* buffer - Memory of buf_size length suitable for calling
* parameter_flashfs_write
* buf_size - The maximum number of bytes that can be written to
* the buffer
*
* Returned value:
* On success the number of bytes written On Error a negative value of errno
*
****************************************************************************/
__EXPORT int parameter_flashfs_alloc(flash_file_token_t ft, uint8_t **buffer, size_t *buf_size);
__END_DECLS
#endif /* _SYSTEMLIB_FLASHPARAMS_NUTTX_PARAM_H */
@@ -0,0 +1,363 @@
/****************************************************************************
*
* Copyright (c) 2015 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file flashparam.c
*
* Global flash based parameter store.
*
* This provides the mechanisms to interface to the PX4
* parameter system but replace the IO with non file based flash
* i/o routines. So that the code my be implemented on a SMALL memory
* foot print device.
*/
#include <px4_defines.h>
#include <px4_posix.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "systemlib/param/param.h"
#include "systemlib/uthash/utarray.h"
#include "systemlib/bson/tinybson.h"
#include "flashparams.h"
#include "flashfs.h"
#if 0
# define debug(fmt, args...) do { warnx(fmt, ##args); } while(0)
#else
# define debug(fmt, args...) do { } while(0)
#endif
/**
* Storage for modified parameters.
*/
struct param_wbuf_s {
param_t param;
union param_value_u val;
bool unsaved;
};
/** lock the parameter store */
static void
param_lock(void)
{
//do {} while (sem_wait(&param_sem) != 0);
}
/** unlock the parameter store */
static void
param_unlock(void)
{
//sem_post(&param_sem);
}
static int
param_export_internal(bool only_unsaved)
{
struct param_wbuf_s *s = NULL;
struct bson_encoder_s encoder;
int result = -1;
param_lock();
/* Use realloc */
bson_encoder_init_buf(&encoder, NULL, 0);
/* no modified parameters -> we are done */
if (param_values == NULL) {
result = 0;
goto out;
}
while ((s = (struct param_wbuf_s *)utarray_next(param_values, s)) != NULL) {
int32_t i;
float f;
/*
* If we are only saving values changed since last save, and this
* one hasn't, then skip it
*/
if (only_unsaved && !s->unsaved) {
continue;
}
s->unsaved = false;
/* append the appropriate BSON type object */
switch (param_type(s->param)) {
case PARAM_TYPE_INT32:
param_get(s->param, &i);
if (bson_encoder_append_int(&encoder, param_name(s->param), i)) {
debug("BSON append failed for '%s'", param_name(s->param));
goto out;
}
break;
case PARAM_TYPE_FLOAT:
param_get(s->param, &f);
if (bson_encoder_append_double(&encoder, param_name(s->param), f)) {
debug("BSON append failed for '%s'", param_name(s->param));
goto out;
}
break;
case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX:
if (bson_encoder_append_binary(&encoder,
param_name(s->param),
BSON_BIN_BINARY,
param_size(s->param),
param_get_value_ptr_external(s->param))) {
debug("BSON append failed for '%s'", param_name(s->param));
goto out;
}
break;
default:
debug("unrecognized parameter type");
goto out;
}
}
result = 0;
out:
param_unlock();
if (result == 0) {
/* Finalize the bison encoding*/
bson_encoder_fini(&encoder);
/* Get requiered space */
size_t buf_size = bson_encoder_buf_size(&encoder);
/* Get a buffer from the flash driver with enough space */
uint8_t *buffer;
result = parameter_flashfs_alloc(parameters_token, &buffer, &buf_size);
if (result == OK) {
void *enc_buff = bson_encoder_buf_data(&encoder);
memcpy(buffer, enc_buff, buf_size);
free(enc_buff);
result = parameter_flashfs_write(parameters_token, buffer, buf_size);
result = result == buf_size ? OK : -EFBIG;
}
}
return result;
}
struct param_import_state {
bool mark_saved;
};
static int
param_import_callback(bson_decoder_t decoder, void *private, bson_node_t node)
{
float f;
int32_t i;
void *v, *tmp = NULL;
int result = -1;
struct param_import_state *state = (struct param_import_state *)private;
/*
* EOO means the end of the parameter object. (Currently not supporting
* nested BSON objects).
*/
if (node->type == BSON_EOO) {
debug("end of parameters");
return 0;
}
/*
* Find the parameter this node represents. If we don't know it,
* ignore the node.
*/
param_t param = param_find_no_notification(node->name);
if (param == PARAM_INVALID) {
debug("ignoring unrecognised parameter '%s'", node->name);
return 1;
}
/*
* Handle setting the parameter from the node
*/
switch (node->type) {
case BSON_INT32:
if (param_type(param) != PARAM_TYPE_INT32) {
debug("unexpected type for '%s", node->name);
goto out;
}
i = node->i;
v = &i;
break;
case BSON_DOUBLE:
if (param_type(param) != PARAM_TYPE_FLOAT) {
debug("unexpected type for '%s", node->name);
goto out;
}
f = node->d;
v = &f;
break;
case BSON_BINDATA:
if (node->subtype != BSON_BIN_BINARY) {
debug("unexpected subtype for '%s", node->name);
goto out;
}
if (bson_decoder_data_pending(decoder) != param_size(param)) {
debug("bad size for '%s'", node->name);
goto out;
}
/* XXX check actual file data size? */
tmp = malloc(param_size(param));
if (tmp == NULL) {
debug("failed allocating for '%s'", node->name);
goto out;
}
if (bson_decoder_copy_data(decoder, tmp)) {
debug("failed copying data for '%s'", node->name);
goto out;
}
v = tmp;
break;
default:
debug("unrecognised node type");
goto out;
}
if (param_set_external(param, v, state->mark_saved, true, false)) {
debug("error setting value for '%s'", node->name);
goto out;
}
if (tmp != NULL) {
free(tmp);
tmp = NULL;
}
/* don't return zero, that means EOF */
result = 1;
out:
if (tmp != NULL) {
free(tmp);
}
return result;
}
static int
param_import_internal(bool mark_saved)
{
struct bson_decoder_s decoder;
int result = -1;
struct param_import_state state;
uint8_t *buffer = 0;
size_t buf_size;
parameter_flashfs_read(parameters_token, &buffer, &buf_size);
if (bson_decoder_init_buf(&decoder, buffer, buf_size, param_import_callback, &state)) {
debug("decoder init failed");
goto out;
}
state.mark_saved = mark_saved;
do {
result = bson_decoder_next(&decoder);
} while (result > 0);
out:
if (result < 0) {
debug("BSON error decoding parameters");
}
return result;
}
int flash_param_save(void)
{
return param_export_internal(false);
}
int flash_param_save_default(void)
{
return param_export_internal(false);
}
int flash_param_load(void)
{
param_reset_all();
return param_import_internal(true);
}
int flash_param_import(void)
{
return 0;
}
@@ -0,0 +1,73 @@
/****************************************************************************
*
* Copyright (c) 2015 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file param.h
*
* Global flash based parameter store.
*
* This provides the mechanisms to interface to the PX4
* parameter system but replace the IO with non file based flash
* i/o routines. So that the code my be implemented on a SMALL memory
* foot print device.
*
*/
#ifndef _SYSTEMLIB_FLASHPARAMS_FLASHPARAMS_H
#define _SYSTEMLIB_FLASHPARAMS_FLASHPARAMS_H
#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>
#include "systemlib/uthash/utarray.h"
__BEGIN_DECLS
/*
* When using the flash based parameter store we have to force
* the param_values and 2 functions to be global
*/
#define FLASH_PARAMS_EXPOSE __EXPORT
__EXPORT extern UT_array *param_values;
__EXPORT int param_set_external(param_t param, const void *val, bool mark_saved, bool notify_changes, bool is_saved);
__EXPORT const void *param_get_value_ptr_external(param_t param);
/* The interface hooks to the Flash based storage */
__EXPORT int flash_param_save(void);
__EXPORT int flash_param_save_default(void);
__EXPORT int flash_param_load(void);
__EXPORT int flash_param_import(void);
__END_DECLS
#endif /* _SYSTEMLIB_FLASHPARAMS_FLASHPARAMS_H */
+42 -8
View File
@@ -63,12 +63,21 @@
#include "systemlib/uthash/utarray.h"
#include "systemlib/bson/tinybson.h"
#include "uORB/uORB.h"
#include "uORB/topics/parameter_update.h"
#include "px4_parameters.h"
#if !defined(PARAM_NO_ORB)
# include "uORB/uORB.h"
# include "uORB/topics/parameter_update.h"
#endif
#if !defined(FLASH_BASED_PARAMS)
# define FLASH_PARAMS_EXPOSE
#else
# include "systemlib/flashparams/flashparams.h"
#endif
#include "px4_parameters.h"
#include <crc32.h>
#if 0
# define debug(fmt, args...) do { warnx(fmt, ##args); } while(0)
#else
@@ -131,13 +140,16 @@ get_param_info_count(void)
}
/** flexible array holding modified parameter values */
UT_array *param_values;
FLASH_PARAMS_EXPOSE UT_array *param_values;
/** array info for the modified parameters array */
const UT_icd param_icd = {sizeof(struct param_wbuf_s), NULL, NULL, NULL};
FLASH_PARAMS_EXPOSE const UT_icd param_icd = {sizeof(struct param_wbuf_s), NULL, NULL, NULL};
#if !defined(PARAM_NO_ORB)
/** parameter update topic handle */
static orb_advert_t param_topic = NULL;
#endif
static void param_set_used_internal(param_t param);
@@ -235,9 +247,11 @@ param_find_changed(param_t param)
static void
param_notify_changes(bool is_saved)
{
struct parameter_update_s pup;
pup.timestamp = hrt_absolute_time();
pup.saved = is_saved;
#if !defined(PARAM_NO_ORB)
struct parameter_update_s pup = {
.timestamp = hrt_absolute_time(),
.saved = is_saved
};
/*
* If we don't have a handle to our topic, create one now; otherwise
@@ -249,6 +263,8 @@ param_notify_changes(bool is_saved)
} else {
orb_publish(ORB_ID(parameter_update), param_topic, &pup);
}
#endif
}
param_t
@@ -436,6 +452,7 @@ param_size(param_t param)
return 0;
}
/**
* Obtain a pointer to the storage allocated for a parameter.
*
@@ -583,6 +600,19 @@ out:
return result;
}
#if defined(FLASH_BASED_PARAMS)
int param_set_external(param_t param, const void *val, bool mark_saved, bool notify_changes, bool is_saved)
{
return param_set_internal(param, val, mark_saved, notify_changes, is_saved);
}
const void *param_get_value_ptr_external(param_t param)
{
return param_get_value_ptr(param);
}
#endif
int
param_set(param_t param, const void *val)
{
@@ -734,6 +764,7 @@ int
param_save_default(void)
{
int res;
#if !defined(FLASH_BASED_PARAMS)
int fd;
const char *filename = param_get_default_file();
@@ -759,6 +790,9 @@ param_save_default(void)
}
PARAM_CLOSE(fd);
#else
res = flash_param_save();
#endif
return res;
}
+4
View File
@@ -120,6 +120,10 @@ typedef param_t px4_param_t;
#define PRId64 "lld"
#endif
#if !defined(offsetof)
# define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
#endif
/*
* POSIX Specific defines
*/
+41 -1
View File
@@ -55,6 +55,9 @@
#include "systemlib/systemlib.h"
#include "systemlib/param/param.h"
#if defined(FLASH_BASED_PARAMS)
# include "systemlib/flashparams/flashparams.h"
#endif
#include "systemlib/err.h"
__EXPORT int param_main(int argc, char *argv[]);
@@ -65,6 +68,7 @@ enum COMPARE_OPERATOR {
};
static int do_save(const char *param_file_name);
static int do_save_default(void);
static int do_load(const char *param_file_name);
static int do_import(const char *param_file_name);
static int do_show(const char *search_string);
@@ -84,7 +88,7 @@ param_main(int argc, char *argv[])
return do_save(argv[2]);
} else {
if (param_save_default()) {
if (do_save_default()) {
warnx("Param export failed.");
return 1;
@@ -213,6 +217,35 @@ param_main(int argc, char *argv[])
return 1;
}
#if defined(FLASH_BASED_PARAMS)
/* If flash based parameters are uses we call out
* to the following set of flash routines
*/
static int
do_save(const char *param_file_name)
{
return flash_param_save();
}
static int
do_save_default(void)
{
return flash_param_save_default();
}
static int
do_load(const char *param_file_name)
{
return flash_param_load();
}
static int
do_import(const char *param_file_name)
{
return flash_param_import();
}
#else
static int
do_save(const char *param_file_name)
{
@@ -238,6 +271,12 @@ do_save(const char *param_file_name)
return 0;
}
static int
do_save_default(void)
{
return param_save_default();
}
static int
do_load(const char *param_file_name)
{
@@ -279,6 +318,7 @@ do_import(const char *param_file_name)
return 0;
}
#endif
static int
do_show(const char *search_string)