PX4 Firmware
PX4 Autopilot Software http://px4.io
flashparams.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2015 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file flashparam.c
36  *
37  * Global flash based parameter store.
38  *
39  * This provides the mechanisms to interface to the PX4
40  * parameter system but replace the IO with non file based flash
41  * i/o routines. So that the code my be implemented on a SMALL memory
42  * foot print device.
43  */
44 
45 #include <px4_platform_common/defines.h>
46 #include <px4_platform_common/posix.h>
47 #include <px4_platform_common/shutdown.h>
48 
49 #include <string.h>
50 #include <stdbool.h>
51 #include <stdint.h>
52 #include <errno.h>
53 
54 #include <parameters/param.h>
55 
58 #include "flashparams.h"
59 #include "flashfs.h"
60 
61 #if 0
62 # define debug(fmt, args...) do { warnx(fmt, ##args); } while(0)
63 #else
64 # define debug(fmt, args...) do { } while(0)
65 #endif
66 
67 
68 /**
69  * Storage for modified parameters.
70  */
71 struct param_wbuf_s {
74  bool unsaved;
75 };
76 
77 static int
78 param_export_internal(bool only_unsaved)
79 {
80  struct param_wbuf_s *s = nullptr;
81  struct bson_encoder_s encoder;
82  int result = -1;
83 
84  /* Use realloc */
85 
86  bson_encoder_init_buf(&encoder, nullptr, 0);
87 
88  /* no modified parameters -> we are done */
89  if (param_values == nullptr) {
90  result = 0;
91  goto out;
92  }
93 
94  while ((s = (struct param_wbuf_s *)utarray_next(param_values, s)) != nullptr) {
95 
96  int32_t i;
97  float f;
98 
99  /*
100  * If we are only saving values changed since last save, and this
101  * one hasn't, then skip it
102  */
103  if (only_unsaved && !s->unsaved) {
104  continue;
105  }
106 
107  s->unsaved = false;
108 
109  /* append the appropriate BSON type object */
110 
111  switch (param_type(s->param)) {
112 
113  case PARAM_TYPE_INT32:
114  i = s->val.i;
115 
116  if (bson_encoder_append_int(&encoder, param_name(s->param), i)) {
117  debug("BSON append failed for '%s'", param_name(s->param));
118  goto out;
119  }
120 
121  break;
122 
123  case PARAM_TYPE_FLOAT:
124  f = s->val.f;
125 
126  if (bson_encoder_append_double(&encoder, param_name(s->param), f)) {
127  debug("BSON append failed for '%s'", param_name(s->param));
128  goto out;
129  }
130 
131  break;
132 
134  if (bson_encoder_append_binary(&encoder,
135  param_name(s->param),
137  param_size(s->param),
139  debug("BSON append failed for '%s'", param_name(s->param));
140  goto out;
141  }
142 
143  break;
144 
145  default:
146  debug("unrecognized parameter type");
147  goto out;
148  }
149  }
150 
151  result = 0;
152 
153 out:
154 
155  if (result == 0) {
156 
157  /* Finalize the bison encoding*/
158 
159  bson_encoder_fini(&encoder);
160 
161  /* Get requiered space */
162 
163  size_t buf_size = bson_encoder_buf_size(&encoder);
164 
165  int shutdown_lock_ret = px4_shutdown_lock();
166 
167  if (shutdown_lock_ret) {
168  PX4_ERR("px4_shutdown_lock() failed (%i)", shutdown_lock_ret);
169  }
170 
171  /* Get a buffer from the flash driver with enough space */
172 
173  uint8_t *buffer;
174  result = parameter_flashfs_alloc(parameters_token, &buffer, &buf_size);
175 
176  if (result == OK) {
177 
178  /* Check for a write that has no changes */
179 
180  uint8_t *was_buffer;
181  size_t was_buf_size;
182  int was_result = parameter_flashfs_read(parameters_token, &was_buffer, &was_buf_size);
183 
184  void *enc_buff = bson_encoder_buf_data(&encoder);
185 
186  bool commit = was_result < OK || was_buf_size != buf_size || 0 != memcmp(was_buffer, enc_buff, was_buf_size);
187 
188  if (commit) {
189 
190  memcpy(buffer, enc_buff, buf_size);
191  result = parameter_flashfs_write(parameters_token, buffer, buf_size);
192  result = result == buf_size ? OK : -EFBIG;
193 
194  }
195 
196  free(enc_buff);
198  }
199 
200  if (shutdown_lock_ret == 0) {
201  px4_shutdown_unlock();
202  }
203 
204  }
205 
206  return result;
207 }
208 
211 };
212 
213 static int
215 {
216  float f;
217  int32_t i;
218  void *v, *tmp = nullptr;
219  int result = -1;
220  struct param_import_state *state = (struct param_import_state *)priv;
221 
222  /*
223  * EOO means the end of the parameter object. (Currently not supporting
224  * nested BSON objects).
225  */
226  if (node->type == BSON_EOO) {
227  debug("end of parameters");
228  return 0;
229  }
230 
231  /*
232  * Find the parameter this node represents. If we don't know it,
233  * ignore the node.
234  */
236 
237  if (param == PARAM_INVALID) {
238  debug("ignoring unrecognised parameter '%s'", node->name);
239  return 1;
240  }
241 
242  /*
243  * Handle setting the parameter from the node
244  */
245 
246  switch (node->type) {
247  case BSON_INT32:
248  if (param_type(param) != PARAM_TYPE_INT32) {
249  PX4_WARN("unexpected type for %s", node->name);
250  result = 1; // just skip this entry
251  goto out;
252  }
253 
254  i = node->i;
255  v = &i;
256  break;
257 
258  case BSON_DOUBLE:
259  if (param_type(param) != PARAM_TYPE_FLOAT) {
260  PX4_WARN("unexpected type for %s", node->name);
261  result = 1; // just skip this entry
262  goto out;
263  }
264 
265  f = node->d;
266  v = &f;
267  break;
268 
269  case BSON_BINDATA:
270  if (node->subtype != BSON_BIN_BINARY) {
271  PX4_WARN("unexpected type for %s", node->name);
272  result = 1; // just skip this entry
273  goto out;
274  }
275 
276  if (bson_decoder_data_pending(decoder) != param_size(param)) {
277  PX4_WARN("bad size for '%s'", node->name);
278  result = 1; // just skip this entry
279  goto out;
280  }
281 
282  /* XXX check actual file data size? */
283  tmp = malloc(param_size(param));
284 
285  if (tmp == nullptr) {
286  debug("failed allocating for '%s'", node->name);
287  goto out;
288  }
289 
290  if (bson_decoder_copy_data(decoder, tmp)) {
291  debug("failed copying data for '%s'", node->name);
292  goto out;
293  }
294 
295  v = tmp;
296  break;
297 
298  default:
299  debug("unrecognised node type");
300  goto out;
301  }
302 
303  if (param_set_external(param, v, state->mark_saved, true)) {
304 
305  debug("error setting value for '%s'", node->name);
306  goto out;
307  }
308 
309  if (tmp != nullptr) {
310  free(tmp);
311  tmp = nullptr;
312  }
313 
314  /* don't return zero, that means EOF */
315  result = 1;
316 
317 out:
318 
319  if (tmp != nullptr) {
320  free(tmp);
321  }
322 
323  return result;
324 }
325 
326 static int
328 {
329  struct bson_decoder_s decoder;
330  int result = -1;
331  struct param_import_state state;
332 
333  uint8_t *buffer = 0;
334  size_t buf_size;
335  parameter_flashfs_read(parameters_token, &buffer, &buf_size);
336 
337  if (bson_decoder_init_buf(&decoder, buffer, buf_size, param_import_callback, &state)) {
338  debug("decoder init failed");
339  goto out;
340  }
341 
342  state.mark_saved = mark_saved;
343 
344  do {
345  result = bson_decoder_next(&decoder);
346 
347  } while (result > 0);
348 
349 out:
350 
351  if (result < 0) {
352  debug("BSON error decoding parameters");
353  }
354 
355  return result;
356 }
357 
358 int flash_param_save(bool only_unsaved)
359 {
360  return param_export_internal(only_unsaved);
361 }
362 
364 {
365  param_reset_all();
366  return param_import_internal(true);
367 }
368 
370 {
371  return param_import_internal(false);
372 }
__EXPORT param_t param_find_no_notification(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:376
#define PARAM_INVALID
Handle returned when a parameter cannot be found.
Definition: param.h:103
__EXPORT size_t param_size(param_t param)
Determine the size of a parameter.
Definition: parameters.cpp:525
int flash_param_save(bool only_unsaved)
char name[BSON_MAXNAME]
Definition: tinybson.h:85
void * bson_encoder_buf_data(bson_encoder_t encoder)
Get a pointer to the encoded object buffer.
Definition: tinybson.cpp:527
int bson_decoder_next(bson_decoder_t decoder)
Process the next node from the stream and invoke the callback.
Definition: tinybson.cpp:180
static enum @74 state
#define PARAM_TYPE_INT32
Parameter types.
Definition: param.h:60
int bson_encoder_append_binary(bson_encoder_t encoder, const char *name, bson_binary_subtype_t subtype, size_t size, const void *data)
Append a binary blob to the encoded stream.
Definition: tinybson.cpp:614
__BEGIN_DECLS __EXPORT UT_array * param_values
flexible array holding modified parameter values
Definition: parameters.cpp:144
#define PARAM_TYPE_STRUCT
Definition: param.h:62
Storage for modified parameters.
Definition: flashparams.cpp:71
bson_binary_subtype_t subtype
Definition: tinybson.h:87
__EXPORT int param_set_external(param_t param, const void *val, bool mark_saved, bool notify_changes)
__EXPORT const flash_file_token_t parameters_token
Encoder state structure.
Definition: tinybson.h:173
union param_value_u val
Definition: flashparams.cpp:72
__EXPORT const void * param_get_value_ptr_external(param_t param)
int bson_decoder_copy_data(bson_decoder_t decoder, void *buf)
Copy node data.
Definition: tinybson.cpp:312
static int param_import_callback(bson_decoder_t decoder, void *priv, bson_node_t node)
int32_t i
Definition: param.h:418
Node structure passed to the callback.
Definition: tinybson.h:84
__EXPORT void parameter_flashfs_free(void)
A simple subset SAX-style BSON parser and generator.
Global flash based parameter store.
int bson_encoder_append_double(bson_encoder_t encoder, const char *name, double value)
Append a double to the encoded stream.
Definition: tinybson.cpp:580
int flash_param_load()
__EXPORT const char * param_name(param_t param)
Obtain the name of a parameter.
Definition: parameters.cpp:486
int flash_param_import()
static int param_import_internal(bool mark_saved)
Parameter value union.
Definition: param.h:416
int bson_decoder_init_buf(bson_decoder_t decoder, void *buf, unsigned bufsize, bson_decoder_callback callback, void *priv)
Initialise the decoder to read from a buffer in memory.
Definition: tinybson.cpp:137
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
size_t bson_decoder_data_pending(bson_decoder_t decoder)
Report copyable data size.
Definition: tinybson.cpp:331
#define PARAM_TYPE_STRUCT_MAX
Definition: param.h:63
__EXPORT param_type_t param_type(param_t param)
Obtain the type of a parameter.
Definition: parameters.cpp:519
#define utarray_next(a, e)
Definition: utarray.h:215
__EXPORT int parameter_flashfs_alloc(flash_file_token_t ft, uint8_t **buffer, size_t *buf_size)
#define debug(fmt, args...)
Definition: flashparams.cpp:64
int bson_encoder_fini(bson_encoder_t encoder)
Finalise the encoded stream.
Definition: tinybson.cpp:484
bson_type_t type
Definition: tinybson.h:86
__EXPORT int parameter_flashfs_read(flash_file_token_t ft, uint8_t **buffer, size_t *buf_size)
#define PARAM_TYPE_FLOAT
Definition: param.h:61
int bson_encoder_buf_size(bson_encoder_t encoder)
Fetch the size of the encoded object; only valid for buffer operations.
Definition: tinybson.cpp:515
__EXPORT int parameter_flashfs_write(flash_file_token_t ft, uint8_t *buffer, size_t buf_size)
int bson_encoder_init_buf(bson_encoder_t encoder, void *buf, unsigned bufsize)
Initialze the encoder for writing to a buffer.
Definition: tinybson.cpp:460
__EXPORT void param_reset_all(void)
Reset all parameters to their default values.
Definition: parameters.cpp:910
float f
Definition: param.h:419
static int param_export_internal(bool only_unsaved)
Definition: flashparams.cpp:78
param_t param
Definition: flashparams.cpp:73
#define OK
Definition: uavcan_main.cpp:71
int64_t i
Definition: tinybson.h:89
double d
Definition: tinybson.h:90
int bson_encoder_append_int(bson_encoder_t encoder, const char *name, int64_t value)
Append an integer to the encoded stream.
Definition: tinybson.cpp:552
uint32_t param_t
Parameter handle.
Definition: param.h:98