Skip to content

Commit edacecd

Browse files
committed
Merge branch 'constparam'
2 parents 4b56d19 + 119c858 commit edacecd

36 files changed

+346
-336
lines changed

include/param/param.h

Lines changed: 116 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
#include <stdint.h>
1212
#include <csp/csp_types.h>
13-
#include <vmem/vmem.h>
1413

1514
#include <libparam.h>
1615

@@ -42,6 +41,31 @@ typedef enum {
4241
PARAM_TYPE_INVALID,
4342
} param_type_e;
4443

44+
#define PARAM_CTYPE_PARAM_TYPE_UINT8 uint8_t
45+
#define PARAM_CTYPE_PARAM_TYPE_UINT16 uint16_t
46+
#define PARAM_CTYPE_PARAM_TYPE_UINT32 uint32_t
47+
#define PARAM_CTYPE_PARAM_TYPE_UINT64 uint64_t
48+
#define PARAM_CTYPE_PARAM_TYPE_INT8 int8_t
49+
#define PARAM_CTYPE_PARAM_TYPE_INT16 int16_t
50+
#define PARAM_CTYPE_PARAM_TYPE_INT32 int32_t
51+
#define PARAM_CTYPE_PARAM_TYPE_INT64 int64_t
52+
#define PARAM_CTYPE_PARAM_TYPE_XINT8 uint8_t
53+
#define PARAM_CTYPE_PARAM_TYPE_XINT16 uint16_t
54+
#define PARAM_CTYPE_PARAM_TYPE_XINT32 uint32_t
55+
#define PARAM_CTYPE_PARAM_TYPE_XINT64 uint64_t
56+
#define PARAM_CTYPE_PARAM_TYPE_FLOAT float
57+
#define PARAM_CTYPE_PARAM_TYPE_DOUBLE double
58+
#define PARAM_CTYPE_PARAM_TYPE_STRING char
59+
#define PARAM_CTYPE_PARAM_TYPE_DATA char
60+
61+
62+
/* “Selector” macro */
63+
#define PARAM_CTYPE(_ptype_token) PARAM_CTYPE_##_ptype_token
64+
65+
/* Deriver sizeof/alignof fra token */
66+
#define PARAM_SIZEOF(_ptype_token) (sizeof(PARAM_CTYPE(_ptype_token)))
67+
#define PARAM_ALIGNOF(_ptype_token) (_Alignof(PARAM_CTYPE(_ptype_token)))
68+
4569
/**
4670
* Global parameter mask
4771
*/
@@ -90,37 +114,36 @@ typedef enum {
90114
/**
91115
* Parameter description structure
92116
* Note: this is not packed in order to maximise run-time efficiency
117+
* But the order of the elements is chosen to minimize padding.
118+
* So we start by largest types first, down to smallest types.
93119
*/
94120
typedef struct param_s {
121+
122+
uint64_t vaddr; /* Virtual address in case of VMEM */
95123

96-
/* Parameter declaration */
97-
uint16_t id;
98124
uint16_t * node;
99-
param_type_e type;
100-
uint32_t mask;
101125
char *name;
102126
char *unit;
103127
char *docstr;
104-
105-
/* Storage */
106128
void * addr; /* Physical address */
107-
uint64_t vaddr; /* Virtual address in case of VMEM */
108-
struct vmem_s * vmem;
109-
int array_size;
110-
int array_step;
129+
const struct vmem_s * vmem;
130+
void (*callback)(const struct param_s * param, int offset);
111131

112-
/* Local info */
113-
void (*callback)(struct param_s * param, int offset);
114-
#ifdef PARAM_HAVE_TIMESTAMP
132+
#ifdef PARAM_HAVE_TIMESTAMP
115133
csp_timestamp_t * timestamp;
116-
#endif
117-
118-
#ifdef PARAM_HAVE_SYS_QUEUE
134+
#endif
135+
136+
#ifdef PARAM_HAVE_SYS_QUEUE
119137
/* single linked list:
120-
* The weird definition format comes from sys/queue.h SLINST_ENTRY() macro */
138+
* The weird definition format comes from sys/queue.h SLINST_ENTRY() macro */
121139
struct { struct param_s *sle_next; } next;
122-
#endif
140+
#endif
123141

142+
uint32_t mask;
143+
uint16_t id;
144+
uint16_t array_step; // Deliberate use of 16-bit to balance speed and size
145+
uint16_t array_size; // Deliberate use of 16-bit to balance speed and size
146+
uint16_t type; // Deliberate use of 16-bit to balance speed and size
124147

125148
} param_t;
126149

@@ -149,16 +172,55 @@ typedef struct param_s {
149172
#define PARAM_TIMESTAMP_INIT(_name)
150173
#endif
151174

175+
static const uint16_t node_self = 0;
176+
177+
#define STR1(x) #x
178+
#define STR(x) STR1(x)
179+
180+
/*
181+
* Compile-time type check for param backing storage.
182+
*
183+
* This macro verifies that the C type of the object pointed to by `ptr`
184+
* matches the PARAM_TYPE_* token specified by `_ptype_token`.
185+
*
186+
* It uses the GCC/Clang builtin `__builtin_types_compatible_p(T1, T2)`,
187+
* which evaluates to 1 at compile time if the two types are compatible
188+
* (i.e. the same underlying type), and 0 otherwise.
189+
*
190+
* The result is stored in a uniquely named enum constant to force the
191+
* expression to be an integer constant expression, allowing it to be
192+
* used in a `_Static_assert`.
193+
*
194+
* If the types do not match, compilation fails with a clear error message,
195+
* preventing mismatches such as declaring PARAM_TYPE_UINT16 for a uint8_t
196+
* variable, or passing the address of an array instead of an element.
197+
*
198+
* Notes:
199+
* - This check is evaluated entirely at compile time.
200+
* - No code or data is generated.
201+
* - Requires GCC or Clang (GNU extensions enabled).
202+
*/
203+
#define PARAM_TYPECHECK(_name, _ptype_token, ptr) \
204+
enum { \
205+
param_typecheck__##_name = __builtin_types_compatible_p( \
206+
__typeof__(*(ptr)), PARAM_CTYPE(_ptype_token) \
207+
) \
208+
}; \
209+
_Static_assert(param_typecheck__##_name, \
210+
"param: param_type does not match pointer element type")
211+
212+
152213

153214
#define PARAM_DEFINE_STATIC_RAM(_id, _name, _type, _array_count, _array_step, _flags, _callback, _unit, _physaddr, _docstr) \
154-
; /* Catch const param defines */ \
215+
_Static_assert(((_array_count) <= 1) ? ((_array_step) <= 0) : ((_array_step) >= PARAM_SIZEOF(_type)), "param: array_step invalid for array_count"); \
216+
_Static_assert(((_array_count) <= 1) ? 1 : (((_array_step) % PARAM_ALIGNOF(_type)) == 0U),"param: array_step not aligned to type"); \
217+
PARAM_TYPECHECK(_name, _type, _physaddr); \
155218
PARAM_TIMESTAMP_DECL(_name) \
156-
uint16_t _node_##_name = 0; \
157-
__attribute__((section("param"))) \
158-
__attribute__((used, no_reorder)) \
159-
param_t _name = { \
219+
__attribute__((section("param." STR(_name)))) \
220+
__attribute__((used, aligned(8))) \
221+
const param_t _name = { \
160222
.vmem = NULL, \
161-
.node = &_node_##_name, \
223+
.node = (uint16_t *) &node_self, \
162224
.id = _id, \
163225
.type = _type, \
164226
.name = #_name, \
@@ -174,13 +236,13 @@ typedef struct param_s {
174236
}
175237

176238
#define PARAM_DEFINE_STATIC_VMEM(_id, _name, _type, _array_count, _array_step, _flags, _callback, _unit, _vmem_name, _vmem_addr, _docstr) \
177-
; /* Catch const param defines */ \
239+
_Static_assert(((_array_count) <= 1) ? ((_array_step) <= 0) : ((_array_step) >= PARAM_SIZEOF(_type)), "param: array_step invalid for array_count"); \
240+
_Static_assert(((_array_count) <= 1) ? 1 : (((_array_step) % PARAM_ALIGNOF(_type)) == 0U),"param: array_step not aligned to type"); \
178241
PARAM_TIMESTAMP_DECL(_name) \
179-
uint16_t _node_##_name = 0; \
180-
__attribute__((section("param"))) \
181-
__attribute__((used, no_reorder)) \
182-
param_t _name = { \
183-
.node = &_node_##_name, \
242+
__attribute__((section("param." STR(_name)))) \
243+
__attribute__((used, aligned(8))) \
244+
const param_t _name = { \
245+
.node = (uint16_t *) &node_self, \
184246
.id = _id, \
185247
.type = _type, \
186248
.name = #_name, \
@@ -199,11 +261,13 @@ typedef struct param_s {
199261
#define PARAM_REMOTE_NODE_IGNORE 16382
200262

201263
#define PARAM_DEFINE_REMOTE(_id, _name, _nodeaddr, _type, _array_count, _array_step, _flags, _physaddr, _docstr) \
202-
; /* Catch const param defines */ \
264+
_Static_assert(((_array_count) <= 1) ? ((_array_step) <= 0) : ((_array_step) >= PARAM_SIZEOF(_type)), "param: array_step invalid for array_count"); \
265+
_Static_assert(((_array_count) <= 1) ? 1 : (((_array_step) % PARAM_ALIGNOF(_type)) == 0U),"param: array_step not aligned to type"); \
266+
PARAM_TYPECHECK(_name, _type, _physaddr); \
203267
PARAM_TIMESTAMP_DECL(_name) \
204-
__attribute__((section("param"))) \
205-
__attribute__((used, no_reorder)) \
206-
param_t _name = { \
268+
__attribute__((section("param." STR(_name)))) \
269+
__attribute__((used, aligned(8))) \
270+
const param_t _name = { \
207271
.node = _nodeaddr, \
208272
.id = _id, \
209273
.type = _type, \
@@ -219,7 +283,9 @@ typedef struct param_s {
219283
};
220284

221285
#define PARAM_DEFINE_REMOTE_DYNAMIC(_id, _name, _node, _type, _array_count, _array_step, _flags, _physaddr, _docstr) \
222-
; /* Catch const param defines */ \
286+
_Static_assert(((_array_count) <= 1) ? ((_array_step) <= 0) : ((_array_step) >= PARAM_SIZEOF(_type)), "param: array_step invalid for array_count"); \
287+
_Static_assert(((_array_count) <= 1) ? 1 : (((_array_step) % PARAM_ALIGNOF(_type)) == 0U),"param: array_step not aligned to type"); \
288+
PARAM_TYPECHECK(_name, _type, _physaddr); \
223289
PARAM_TIMESTAMP_DECL(_name) \
224290
uint16_t _node_##_name = _node; \
225291
param_t _name = { \
@@ -239,8 +305,8 @@ typedef struct param_s {
239305

240306
/* Native getter functions, will return native types */
241307
#define PARAM_GET(type, name) \
242-
type param_get_##name(param_t * param); \
243-
type param_get_##name##_array(param_t * param, unsigned int i);
308+
type param_get_##name(const param_t * param); \
309+
type param_get_##name##_array(const param_t * param, unsigned int i);
244310
PARAM_GET(uint8_t, uint8)
245311
PARAM_GET(uint16_t, uint16)
246312
PARAM_GET(uint32_t, uint32)
@@ -255,10 +321,10 @@ PARAM_GET(double, double)
255321

256322
/* Native setter functions, these take a native type as argument */
257323
#define PARAM_SET(type, name) \
258-
void param_set_##name(param_t * param, type value); \
259-
void param_set_##name##_nocallback(param_t * param, type value); \
260-
void param_set_##name##_array(param_t * param, unsigned int i, type value); \
261-
void param_set_##name##_array_nocallback(param_t * param, unsigned int i, type value);
324+
void param_set_##name(const param_t * param, type value); \
325+
void param_set_##name##_nocallback(const param_t * param, type value); \
326+
void param_set_##name##_array(const param_t * param, unsigned int i, type value); \
327+
void param_set_##name##_array_nocallback(const param_t * param, unsigned int i, type value);
262328
PARAM_SET(uint8_t, uint8)
263329
PARAM_SET(uint16_t, uint16)
264330
PARAM_SET(uint32_t, uint32)
@@ -272,24 +338,24 @@ PARAM_SET(double, double)
272338
#undef PARAM_SET
273339

274340
/* Non-native types needs to go through a function which includes a void pointer and the length */
275-
void param_set_data(param_t * param, const void * inbuf, int len);
276-
void param_set_data_nocallback(param_t * param, const void * inbuf, int len);
277-
void param_get_data(param_t * param, void * outbuf, int len);
278-
void param_set_string(param_t * param, const char * inbuf, int len);
341+
void param_set_data(const param_t * param, const void * inbuf, int len);
342+
void param_set_data_nocallback(const param_t * param, const void * inbuf, int len);
343+
void param_get_data(const param_t * param, void * outbuf, int len);
344+
void param_set_string(const param_t * param, const char * inbuf, int len);
279345
#define param_get_string param_get_data
280346

281347
/* Generic setter function:
282348
* This function can be used to set data of any type
283349
*/
284-
void param_set(param_t * param, unsigned int offset, void * value);
285-
void param_get(param_t * param, unsigned int offset, void * value);
350+
void param_set(const param_t * param, unsigned int offset, void * value);
351+
void param_get(const param_t * param, unsigned int offset, void * value);
286352

287353
/* Returns the size of a native type */
288354
int param_typesize(param_type_e type);
289-
int param_size(param_t * param);
355+
int param_size(const param_t * param);
290356

291357
/* Copies from one parameter to another */
292-
void param_copy(param_t * dest, param_t * src);
358+
void param_copy(const param_t * dest, const param_t * src);
293359

294360
/* External hooks to get atomic writes */
295361
extern __attribute__((weak)) void param_enter_critical(void);

include/param/param_client.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
* @param version 1 or 2
3636
* @return 0 = ok, -1 on network error
3737
*/
38-
int param_pull_single(param_t *param, int offset, int prio, int verbose, int host, int timeout, int version);
38+
int param_pull_single(const param_t *param, int offset, int prio, int verbose, int host, int timeout, int version);
3939

4040
/**
4141
* PULL all
@@ -65,7 +65,7 @@ int param_pull_all(int prio, int verbose, int host, uint32_t include_mask, uint3
6565
* @param ack_with_pull ack with param queue
6666
* @return 0 = OK, -1 on network error
6767
*/
68-
int param_push_single(param_t *param, int offset, int prio, void *value, int verbose, int host, int timeout, int version, bool ack_with_pull);
68+
int param_push_single(const param_t *param, int offset, int prio, void *value, int verbose, int host, int timeout, int version, bool ack_with_pull);
6969

7070
/**
7171
* QUEUE PARAMETER API

include/param/param_list.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ extern "C" {
1717

1818
typedef struct param_list_iterator_s {
1919
int phase; // Hybrid iterator has multiple phases (0 == Static, 1 == Dynamic List)
20-
param_t * element;
20+
const param_t * element;
2121
} param_list_iterator;
2222

23-
param_t * param_list_iterate(param_list_iterator * iterator);
23+
const param_t * param_list_iterate(param_list_iterator * iterator);
2424

2525
int param_list_add(param_t * item);
2626

@@ -40,13 +40,13 @@ int param_list_remove(int node, uint8_t verbose);
4040
* @param verbose Whether to print the removed parameter.
4141
* @return int 1 if the parameter was found and removed.
4242
*/
43-
void param_list_remove_specific(param_t * param, uint8_t verbose, int destroy);
44-
param_t * param_list_find_id(int node, int id);
45-
param_t * param_list_find_name(int node, const char * name);
43+
void param_list_remove_specific(const param_t * param, uint8_t verbose, int destroy);
44+
const param_t * param_list_find_id(int node, int id);
45+
const param_t * param_list_find_name(int node, const char * name);
4646
void param_list_print(uint32_t mask, int node, const char * globstr, int verbosity);
4747
uint32_t param_maskstr_to_mask(const char * str);
4848

49-
param_t * param_list_from_line(const char * line);
49+
const param_t * param_list_from_line(const char * line);
5050

5151
/**
5252
* @brief
@@ -64,8 +64,8 @@ param_t * param_list_from_line(const char * line);
6464
*/
6565
param_t * param_list_create_remote(int id, int node, int type, uint32_t mask, int array_size, char * name, char * unit, char * help, int storage_type);
6666

67-
void param_list_destroy(param_t * param);
68-
void param_print(param_t * param, int offset, int nodes[], int nodes_count, int verbose, uint32_t ref_timestamp);
67+
void param_list_destroy(const param_t * param);
68+
void param_print(const param_t * param, int offset, int nodes[], int nodes_count, int verbose, uint32_t ref_timestamp);
6969

7070
unsigned int param_list_packed_size(int list_version);
7171
int param_list_unpack(int node, void * data, int length, int list_version, int include_remotes);

include/param/param_queue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ typedef struct param_queue_s {
3636

3737
void param_queue_init(param_queue_t * queue, void * buffer, int buffer_size, int used, param_queue_type_e type, int version);
3838

39-
int param_queue_add(param_queue_t *queue, param_t *param, int offset, void *value);
39+
int param_queue_add(param_queue_t *queue, const param_t *param, int offset, void *value);
4040

4141
/**
4242
* @brief Applies the content of a queue to memory.

include/param/param_serializer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
#include <csp/csp.h>
1414
#include <mpack/mpack.h>
1515

16-
void param_serialize_id(mpack_writer_t *writer, param_t * param, int offset, param_queue_t * queue);
16+
void param_serialize_id(mpack_writer_t *writer, const param_t * param, int offset, param_queue_t * queue);
1717
void param_deserialize_id(mpack_reader_t *reader, int *id, int *node, csp_timestamp_t *timestamp, int *offset, param_queue_t * queue);
1818

19-
int param_serialize_to_mpack(param_t * param, int offset, mpack_writer_t * writer, void * value, param_queue_t * queue);
20-
void param_deserialize_from_mpack_to_param(void * context, void * queue, param_t * param, int offset, mpack_reader_t * reader);
19+
int param_serialize_to_mpack(const param_t * param, int offset, mpack_writer_t * writer, void * value, param_queue_t * queue);
20+
void param_deserialize_from_mpack_to_param(void * context, void * queue, const param_t * param, int offset, mpack_reader_t * reader);
2121

2222
#endif /* SRC_PARAM_PARAM_SERIALIZER_H_ */

include/param/param_server.h

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -74,42 +74,3 @@ typedef enum {
7474
* @param packet
7575
*/
7676
void param_serve(csp_packet_t * packet);
77-
78-
#if PARAM_NUM_PUBLISHQUEUES > 4
79-
#error A maximum number of four param queues are supported
80-
#endif
81-
82-
#if PARAM_NUM_PUBLISHQUEUES > 0
83-
typedef struct param_publish_s {
84-
param_t * param;
85-
uint32_t queue;
86-
} param_publish_t;
87-
88-
typedef enum {
89-
PARAM_PUBLISHQUEUE_0 = 0,
90-
#if PARAM_NUM_PUBLISHQUEUES >= 2
91-
PARAM_PUBLISHQUEUE_1 = 1,
92-
#endif
93-
#if PARAM_NUM_PUBLISHQUEUES >= 3
94-
PARAM_PUBLISHQUEUE_2 = 2,
95-
#endif
96-
#if PARAM_NUM_PUBLISHQUEUES >= 4
97-
PARAM_PUBLISHQUEUE_3 = 3,
98-
#endif
99-
} param_publish_id_t;
100-
101-
#define PARAM_ADD_PUBLISH(paramname, queueid) \
102-
param_publish_t __param_publish_##paramname##queueid = { \
103-
.param = &paramname, \
104-
.queue = queueid, \
105-
}; \
106-
__attribute__((section("param_publish"))) \
107-
param_publish_t const * _param_publish_##paramname##queueid = & __param_publish_##paramname##queueid;
108-
109-
typedef bool (*param_shall_publish_t)(uint8_t queue);
110-
111-
void param_publish_periodic(void);
112-
void param_publish_configure(param_publish_id_t queueid, uint16_t destination, uint16_t periodicity_ms, csp_prio_t csp_prio);
113-
void param_publish_init(param_shall_publish_t criteria_cb);
114-
115-
#endif

0 commit comments

Comments
 (0)