diff --git a/apps/px4/tests/tests.h b/apps/px4/tests/tests.h index aa6dae1e09..f2e35972fb 100644 --- a/apps/px4/tests/tests.h +++ b/apps/px4/tests/tests.h @@ -95,5 +95,6 @@ extern int test_sleep(int argc, char *argv[]); extern int test_time(int argc, char *argv[]); extern int test_uart_console(int argc, char *argv[]); extern int test_jig_voltages(int argc, char *argv[]); +extern int test_param(int argc, char *argv[]); #endif /* __APPS_PX4_TESTS_H */ diff --git a/apps/px4/tests/tests_main.c b/apps/px4/tests/tests_main.c index 268e7d5f9d..a4613288f2 100644 --- a/apps/px4/tests/tests_main.c +++ b/apps/px4/tests/tests_main.c @@ -108,6 +108,7 @@ struct { {"perf", test_perf, OPT_NOJIGTEST, 0}, {"all", test_all, OPT_NOALLTEST | OPT_NOJIGTEST, 0}, {"jig", test_jig, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"param", test_param, 0, 0}, {"help", test_help, OPT_NOALLTEST | OPT_NOHELP | OPT_NOJIGTEST, 0}, {NULL, NULL, 0, 0} }; diff --git a/apps/px4/tests/tests_param.c b/apps/px4/tests/tests_param.c new file mode 100644 index 0000000000..e564bda8ff --- /dev/null +++ b/apps/px4/tests/tests_param.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Lorenz Meier + * + * 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 tests_param.c + * + * Tests related to the parameter system. + */ + +#include +#include "systemlib/err.h" + +#include "systemlib/param/param.h" + +PARAM_DEFINE_INT32(test, 0x12345678); + +int +test_param(int argc, char *argv[]) +{ + param_t p; + + p = param_find("test"); + if (p == PARAM_INVALID) + errx(1, "test parameter not found\n"); + + param_type_t t = param_type(p); + if (t != PARAM_TYPE_INT32) + errx(1, "test parameter type mismatch (got %u)\n", (unsigned)t); + + int32_t val; + if (param_get(p, &val) != 0) + errx(1, "failed to read test parameter\n"); + if (val != 0x12345678) + errx(1, "parameter value mismatch\n"); + + warnx("parameter test PASS\n"); + + return 0; +} diff --git a/apps/systemlib/Makefile b/apps/systemlib/Makefile index 172eef979d..fd6846937f 100644 --- a/apps/systemlib/Makefile +++ b/apps/systemlib/Makefile @@ -37,7 +37,8 @@ CSRCS = err.c \ hx_stream.c \ - perf_counter.c + perf_counter.c \ + param/param.c # # XXX this really should be a CONFIG_* test diff --git a/apps/systemlib/param/param.c b/apps/systemlib/param/param.c new file mode 100644 index 0000000000..bb82941a0c --- /dev/null +++ b/apps/systemlib/param/param.c @@ -0,0 +1,110 @@ +/** + * @file param.c + * + * Global parameter store. + */ + +#include +#include + +#include + +#include "param.h" + +/** + * Array of static parameter info. + */ +extern char __param_start, __param_end; +static const struct param_info_s *param_info_base = (struct param_info_s *)&__param_start; +static const struct param_info_s *param_info_limit = (struct param_info_s *)&__param_end; +#define param_info_count ((unsigned)(param_info_limit - param_info_base)) + +static bool +handle_in_range(param_t handle) +{ + return (handle < param_info_count); +} + +param_t +param_find(const char *name) +{ + param_t param; + + for (param = 0; handle_in_range(param); param++) { + if (!strcmp(param_info_base[param].name, name)) + return param; + } + + /* not found */ + return PARAM_INVALID; +} + +enum +param_type_e param_type(param_t param) +{ + if (handle_in_range(param)) + return param_info_base[param].type; + + return PARAM_TYPE_UNKNOWN; +} + +size_t +param_size(param_t param) +{ + + if (handle_in_range(param)) { + switch (param_info_base[param].type) { + case PARAM_TYPE_INT32: + case PARAM_TYPE_FLOAT: + return 4; + + case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX: + return param_info_base[param].type - PARAM_TYPE_STRUCT; + + default: + return 0; + } + } + + return 0; +} + +int +param_get(param_t param, void *val) +{ + if (handle_in_range(param)) { + + /* XXX look for updated value stored elsewhere */ + + switch (param_info_base[param].type) { + case PARAM_TYPE_INT32: + *(int32_t *)val = param_info_base[param].i; + return 0; + + case PARAM_TYPE_FLOAT: + *(float *)val = param_info_base[param].f; + return 0; + + case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX: + memcpy(val, param_info_base[param].p, param_size(param)); + return 0; + + default: + return -1; + } + } + return -1; +} + +int +param_set(param_t param, void *val) +{ + if (handle_in_range(param)) { + + /* XXX maintain list of changed values */ + + } + return -1; + +} + diff --git a/apps/systemlib/param/param.h b/apps/systemlib/param/param.h new file mode 100644 index 0000000000..9f7808f30a --- /dev/null +++ b/apps/systemlib/param/param.h @@ -0,0 +1,140 @@ +/** + * @file param.h + * + * Global parameter store. + */ + +#ifndef _SYSTEMLIB_PARAM_PARAM_H +#define _SYSTEMLIB_PARAM_PARAM_H + +#include + +/** + * Parameter types. + */ +typedef enum param_type_e +{ + /* globally-known parameter types */ + PARAM_TYPE_INT32 = 0, + PARAM_TYPE_FLOAT, + + /* structure parameters; these are expected to be identified by name */ + PARAM_TYPE_STRUCT = 100, + PARAM_TYPE_STRUCT_MAX = 16384 + PARAM_TYPE_STRUCT, + + PARAM_TYPE_UNKNOWN = 0xffff +} param_type_t; + +/** + * Parameter handle. + * + * Parameters are represented by parameter handles, which can + * be obtained by looking up (or creating?) parameters. + */ +typedef uintptr_t param_t; + +/** + * Handle returned when a parameter cannot be found. + */ +#define PARAM_INVALID ((uintptr_t)0xffffffff) + +/** + * Look up a parameter by name. + * + * @param name The canonical name of the parameter being looked up. + * @return A handle to the parameter, or PARAM_INVALID if the parameter does not exist. + */ +__EXPORT param_t param_find(const char *name); + +/** + * Obtain the type of a parameter. + * + * @param param A handle returned by param_find. + * @return The type assigned to the parameter. + */ +__EXPORT param_type_t param_type(param_t param); + +/** + * Determine the size of a parameter. + * + * @param param A handle returned by param_find. + * @return The size of the parameter's value. + */ +__EXPORT size_t param_size(param_t param); + +/** + * Obtain the scalar value of a parameter. + * + * @param param A handle returned by param_find. + * @param val Where to return the value, assumed to point to suitable storage for the parameter type. + * For structures, a pointer to the structure is returned. + * @return Zero if the parameter's value could be returned as a scalar, nonzero otherwise. + */ +__EXPORT int param_get(param_t param, void *val); + +/** + * Set the scalar value of a parameter. + * + * @param param A handle returned by param_find. + * @param val The value to set; assumed to point to a variable of the parameter type. + * For structures, the pointer is assumed to point to a copy of the structure. + * @return Zero if the parameter's value could be set from a scalar, nonzero otherwise. + */ +__EXPORT int param_set(param_t param, void *val); + +/* + * Macros creating static parameter definitions. + * + * Note that these structures are not known by name; they are + * collected into a section that is iterated by the parameter + * code. + */ + +/** define an int32 parameter */ +#define PARAM_DEFINE_INT32(_name, _default) \ + static const \ + __attribute__((used, section("__param"))) \ + struct param_info_s __param__##_name = { \ + .name = #_name, \ + .type = PARAM_TYPE_INT32, \ + .i = _default \ + } + +/** define a float parameter */ +#define PARAM_DEFINE_FLOAT(_name, _default) \ + static const \ + __attribute__((used, section("__param"))) \ + struct param_info_s __param__##_name = { \ + .name = #_name, \ + .type = PARAM_TYPE_FLOAT, \ + .f = _default \ + } + +/** define a parameter that points to a structure */ +#define PARAM_DEFINE_STRUCT(_name, _default) \ + static const \ + __attribute__((used, section("__param"))) \ + struct param_info_s __param__##_name = { \ + .name = #_name, \ + .type = PARAM_TYPE_STRUCT + sizeof(_default), \ + .p = &_default; \ + } + +/** + * Static parameter definition structure. + * + * This is normally not used by user code; see the PARAM_DEFINE macros + * instead. + */ +struct param_info_s +{ + const char *name; + param_type_t type; + union { + void *p; + int32_t i; + float f; + }; +}; + +#endif