Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
786f19b
Made param_t const
johandc Jan 28, 2026
16f05e3
Make vmem const
johandc Jan 28, 2026
602d7b1
Avoid function scope statics
johandc Jan 29, 2026
122c7c4
force local statics to use address zero
johandc Jan 30, 2026
1a7196d
stop using no_reorder which is an unknown attribute
johandc Feb 1, 2026
db59e06
Reorder param_t for more efficient storage
johandc Feb 2, 2026
bf51584
param client const fix
johandc Feb 2, 2026
43e1681
Do not export __start_vmem
johandc Feb 2, 2026
a77279d
check for null on queue add
johandc Feb 2, 2026
7437cd7
const fix for param_list dynamic
johandc Feb 2, 2026
c2b6319
revert builtin publish queues (moved to userspace)
johandc Feb 2, 2026
1959b6a
Sort param sections by name
johandc Feb 9, 2026
10834b0
fix inttypes
johandc Feb 13, 2026
9922186
Compile with warning level 3 pedantic flags
johandc Feb 13, 2026
8843986
Further increase strictness of compiler warnings
johandc Feb 13, 2026
d5ff3ed
proper inclusion of string.h
johandc Feb 16, 2026
ac00f45
added static asserts on alignment
johandc Feb 16, 2026
2cf8741
remove signed comparison warning
johandc Feb 16, 2026
f8a6465
remove unused parameter warning
johandc Feb 16, 2026
a64c8ee
avoid cast align and void * aritmetic warnings
johandc Feb 16, 2026
487ed85
include string.h
johandc Feb 16, 2026
3835bdd
Reduce warnings til we fix limits.h in picolibc
johandc Feb 16, 2026
523ab94
use sizeof for static assert
johandc Feb 17, 2026
3c97ae7
use const in callback in param_collector
johandc Feb 17, 2026
97fe67f
Better param type check
johandc Feb 17, 2026
948d990
nice little comment to PARAM_TYPECHECK
johandc Feb 17, 2026
119c858
Set xint series as uint types
johandc Feb 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 116 additions & 50 deletions include/param/param.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

#include <stdint.h>
#include <csp/csp_types.h>
#include <vmem/vmem.h>

#include <libparam.h>

Expand Down Expand Up @@ -42,6 +41,31 @@ typedef enum {
PARAM_TYPE_INVALID,
} param_type_e;

#define PARAM_CTYPE_PARAM_TYPE_UINT8 uint8_t
#define PARAM_CTYPE_PARAM_TYPE_UINT16 uint16_t
#define PARAM_CTYPE_PARAM_TYPE_UINT32 uint32_t
#define PARAM_CTYPE_PARAM_TYPE_UINT64 uint64_t
#define PARAM_CTYPE_PARAM_TYPE_INT8 int8_t
#define PARAM_CTYPE_PARAM_TYPE_INT16 int16_t
#define PARAM_CTYPE_PARAM_TYPE_INT32 int32_t
#define PARAM_CTYPE_PARAM_TYPE_INT64 int64_t
#define PARAM_CTYPE_PARAM_TYPE_XINT8 uint8_t
#define PARAM_CTYPE_PARAM_TYPE_XINT16 uint16_t
#define PARAM_CTYPE_PARAM_TYPE_XINT32 uint32_t
#define PARAM_CTYPE_PARAM_TYPE_XINT64 uint64_t
#define PARAM_CTYPE_PARAM_TYPE_FLOAT float
#define PARAM_CTYPE_PARAM_TYPE_DOUBLE double
#define PARAM_CTYPE_PARAM_TYPE_STRING char
#define PARAM_CTYPE_PARAM_TYPE_DATA char


/* “Selector” macro */
#define PARAM_CTYPE(_ptype_token) PARAM_CTYPE_##_ptype_token

/* Deriver sizeof/alignof fra token */
#define PARAM_SIZEOF(_ptype_token) (sizeof(PARAM_CTYPE(_ptype_token)))
#define PARAM_ALIGNOF(_ptype_token) (_Alignof(PARAM_CTYPE(_ptype_token)))

/**
* Global parameter mask
*/
Expand Down Expand Up @@ -90,37 +114,36 @@ typedef enum {
/**
* Parameter description structure
* Note: this is not packed in order to maximise run-time efficiency
* But the order of the elements is chosen to minimize padding.
* So we start by largest types first, down to smallest types.
*/
typedef struct param_s {

uint64_t vaddr; /* Virtual address in case of VMEM */

/* Parameter declaration */
uint16_t id;
uint16_t * node;
param_type_e type;
uint32_t mask;
char *name;
char *unit;
char *docstr;

/* Storage */
void * addr; /* Physical address */
uint64_t vaddr; /* Virtual address in case of VMEM */
struct vmem_s * vmem;
int array_size;
int array_step;
const struct vmem_s * vmem;
void (*callback)(const struct param_s * param, int offset);

/* Local info */
void (*callback)(struct param_s * param, int offset);
#ifdef PARAM_HAVE_TIMESTAMP
#ifdef PARAM_HAVE_TIMESTAMP
csp_timestamp_t * timestamp;
#endif

#ifdef PARAM_HAVE_SYS_QUEUE
#endif
#ifdef PARAM_HAVE_SYS_QUEUE
/* single linked list:
* The weird definition format comes from sys/queue.h SLINST_ENTRY() macro */
* The weird definition format comes from sys/queue.h SLINST_ENTRY() macro */
struct { struct param_s *sle_next; } next;
#endif
#endif

uint32_t mask;
uint16_t id;
uint16_t array_step; // Deliberate use of 16-bit to balance speed and size
uint16_t array_size; // Deliberate use of 16-bit to balance speed and size
uint16_t type; // Deliberate use of 16-bit to balance speed and size

} param_t;

Expand Down Expand Up @@ -149,16 +172,55 @@ typedef struct param_s {
#define PARAM_TIMESTAMP_INIT(_name)
#endif

static const uint16_t node_self = 0;

#define STR1(x) #x
#define STR(x) STR1(x)

/*
* Compile-time type check for param backing storage.
*
* This macro verifies that the C type of the object pointed to by `ptr`
* matches the PARAM_TYPE_* token specified by `_ptype_token`.
*
* It uses the GCC/Clang builtin `__builtin_types_compatible_p(T1, T2)`,
* which evaluates to 1 at compile time if the two types are compatible
* (i.e. the same underlying type), and 0 otherwise.
*
* The result is stored in a uniquely named enum constant to force the
* expression to be an integer constant expression, allowing it to be
* used in a `_Static_assert`.
*
* If the types do not match, compilation fails with a clear error message,
* preventing mismatches such as declaring PARAM_TYPE_UINT16 for a uint8_t
* variable, or passing the address of an array instead of an element.
*
* Notes:
* - This check is evaluated entirely at compile time.
* - No code or data is generated.
* - Requires GCC or Clang (GNU extensions enabled).
*/
#define PARAM_TYPECHECK(_name, _ptype_token, ptr) \
enum { \
param_typecheck__##_name = __builtin_types_compatible_p( \
__typeof__(*(ptr)), PARAM_CTYPE(_ptype_token) \
) \
}; \
_Static_assert(param_typecheck__##_name, \
"param: param_type does not match pointer element type")



#define PARAM_DEFINE_STATIC_RAM(_id, _name, _type, _array_count, _array_step, _flags, _callback, _unit, _physaddr, _docstr) \
; /* Catch const param defines */ \
_Static_assert(((_array_count) <= 1) ? ((_array_step) <= 0) : ((_array_step) >= PARAM_SIZEOF(_type)), "param: array_step invalid for array_count"); \
_Static_assert(((_array_count) <= 1) ? 1 : (((_array_step) % PARAM_ALIGNOF(_type)) == 0U),"param: array_step not aligned to type"); \
PARAM_TYPECHECK(_name, _type, _physaddr); \
PARAM_TIMESTAMP_DECL(_name) \
uint16_t _node_##_name = 0; \
__attribute__((section("param"))) \
__attribute__((used, no_reorder)) \
param_t _name = { \
__attribute__((section("param." STR(_name)))) \
__attribute__((used, aligned(8))) \
const param_t _name = { \
.vmem = NULL, \
.node = &_node_##_name, \
.node = (uint16_t *) &node_self, \
.id = _id, \
.type = _type, \
.name = #_name, \
Expand All @@ -174,13 +236,13 @@ typedef struct param_s {
}

#define PARAM_DEFINE_STATIC_VMEM(_id, _name, _type, _array_count, _array_step, _flags, _callback, _unit, _vmem_name, _vmem_addr, _docstr) \
; /* Catch const param defines */ \
_Static_assert(((_array_count) <= 1) ? ((_array_step) <= 0) : ((_array_step) >= PARAM_SIZEOF(_type)), "param: array_step invalid for array_count"); \
_Static_assert(((_array_count) <= 1) ? 1 : (((_array_step) % PARAM_ALIGNOF(_type)) == 0U),"param: array_step not aligned to type"); \
PARAM_TIMESTAMP_DECL(_name) \
uint16_t _node_##_name = 0; \
__attribute__((section("param"))) \
__attribute__((used, no_reorder)) \
param_t _name = { \
.node = &_node_##_name, \
__attribute__((section("param." STR(_name)))) \
__attribute__((used, aligned(8))) \
const param_t _name = { \
.node = (uint16_t *) &node_self, \
.id = _id, \
.type = _type, \
.name = #_name, \
Expand All @@ -199,11 +261,13 @@ typedef struct param_s {
#define PARAM_REMOTE_NODE_IGNORE 16382

#define PARAM_DEFINE_REMOTE(_id, _name, _nodeaddr, _type, _array_count, _array_step, _flags, _physaddr, _docstr) \
; /* Catch const param defines */ \
_Static_assert(((_array_count) <= 1) ? ((_array_step) <= 0) : ((_array_step) >= PARAM_SIZEOF(_type)), "param: array_step invalid for array_count"); \
_Static_assert(((_array_count) <= 1) ? 1 : (((_array_step) % PARAM_ALIGNOF(_type)) == 0U),"param: array_step not aligned to type"); \
PARAM_TYPECHECK(_name, _type, _physaddr); \
PARAM_TIMESTAMP_DECL(_name) \
__attribute__((section("param"))) \
__attribute__((used, no_reorder)) \
param_t _name = { \
__attribute__((section("param." STR(_name)))) \
__attribute__((used, aligned(8))) \
const param_t _name = { \
.node = _nodeaddr, \
.id = _id, \
.type = _type, \
Expand All @@ -219,7 +283,9 @@ typedef struct param_s {
};

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

/* Native getter functions, will return native types */
#define PARAM_GET(type, name) \
type param_get_##name(param_t * param); \
type param_get_##name##_array(param_t * param, unsigned int i);
type param_get_##name(const param_t * param); \
type param_get_##name##_array(const param_t * param, unsigned int i);
PARAM_GET(uint8_t, uint8)
PARAM_GET(uint16_t, uint16)
PARAM_GET(uint32_t, uint32)
Expand All @@ -255,10 +321,10 @@ PARAM_GET(double, double)

/* Native setter functions, these take a native type as argument */
#define PARAM_SET(type, name) \
void param_set_##name(param_t * param, type value); \
void param_set_##name##_nocallback(param_t * param, type value); \
void param_set_##name##_array(param_t * param, unsigned int i, type value); \
void param_set_##name##_array_nocallback(param_t * param, unsigned int i, type value);
void param_set_##name(const param_t * param, type value); \
void param_set_##name##_nocallback(const param_t * param, type value); \
void param_set_##name##_array(const param_t * param, unsigned int i, type value); \
void param_set_##name##_array_nocallback(const param_t * param, unsigned int i, type value);
PARAM_SET(uint8_t, uint8)
PARAM_SET(uint16_t, uint16)
PARAM_SET(uint32_t, uint32)
Expand All @@ -272,24 +338,24 @@ PARAM_SET(double, double)
#undef PARAM_SET

/* Non-native types needs to go through a function which includes a void pointer and the length */
void param_set_data(param_t * param, const void * inbuf, int len);
void param_set_data_nocallback(param_t * param, const void * inbuf, int len);
void param_get_data(param_t * param, void * outbuf, int len);
void param_set_string(param_t * param, const char * inbuf, int len);
void param_set_data(const param_t * param, const void * inbuf, int len);
void param_set_data_nocallback(const param_t * param, const void * inbuf, int len);
void param_get_data(const param_t * param, void * outbuf, int len);
void param_set_string(const param_t * param, const char * inbuf, int len);
#define param_get_string param_get_data

/* Generic setter function:
* This function can be used to set data of any type
*/
void param_set(param_t * param, unsigned int offset, void * value);
void param_get(param_t * param, unsigned int offset, void * value);
void param_set(const param_t * param, unsigned int offset, void * value);
void param_get(const param_t * param, unsigned int offset, void * value);

/* Returns the size of a native type */
int param_typesize(param_type_e type);
int param_size(param_t * param);
int param_size(const param_t * param);

/* Copies from one parameter to another */
void param_copy(param_t * dest, param_t * src);
void param_copy(const param_t * dest, const param_t * src);

/* External hooks to get atomic writes */
extern __attribute__((weak)) void param_enter_critical(void);
Expand Down
4 changes: 2 additions & 2 deletions include/param/param_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
* @param version 1 or 2
* @return 0 = ok, -1 on network error
*/
int param_pull_single(param_t *param, int offset, int prio, int verbose, int host, int timeout, int version);
int param_pull_single(const param_t *param, int offset, int prio, int verbose, int host, int timeout, int version);

/**
* PULL all
Expand Down Expand Up @@ -65,7 +65,7 @@ int param_pull_all(int prio, int verbose, int host, uint32_t include_mask, uint3
* @param ack_with_pull ack with param queue
* @return 0 = OK, -1 on network error
*/
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);
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);

/**
* QUEUE PARAMETER API
Expand Down
16 changes: 8 additions & 8 deletions include/param/param_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ extern "C" {

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

param_t * param_list_iterate(param_list_iterator * iterator);
const param_t * param_list_iterate(param_list_iterator * iterator);

int param_list_add(param_t * item);

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

param_t * param_list_from_line(const char * line);
const param_t * param_list_from_line(const char * line);

/**
* @brief
Expand All @@ -64,8 +64,8 @@ param_t * param_list_from_line(const char * line);
*/
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);

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

unsigned int param_list_packed_size(int list_version);
int param_list_unpack(int node, void * data, int length, int list_version, int include_remotes);
Expand Down
2 changes: 1 addition & 1 deletion include/param/param_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ typedef struct param_queue_s {

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

int param_queue_add(param_queue_t *queue, param_t *param, int offset, void *value);
int param_queue_add(param_queue_t *queue, const param_t *param, int offset, void *value);

/**
* @brief Applies the content of a queue to memory.
Expand Down
6 changes: 3 additions & 3 deletions include/param/param_serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
#include <csp/csp.h>
#include <mpack/mpack.h>

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

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

#endif /* SRC_PARAM_PARAM_SERIALIZER_H_ */
39 changes: 0 additions & 39 deletions include/param/param_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,42 +74,3 @@ typedef enum {
* @param packet
*/
void param_serve(csp_packet_t * packet);

#if PARAM_NUM_PUBLISHQUEUES > 4
#error A maximum number of four param queues are supported
#endif

#if PARAM_NUM_PUBLISHQUEUES > 0
typedef struct param_publish_s {
param_t * param;
uint32_t queue;
} param_publish_t;

typedef enum {
PARAM_PUBLISHQUEUE_0 = 0,
#if PARAM_NUM_PUBLISHQUEUES >= 2
PARAM_PUBLISHQUEUE_1 = 1,
#endif
#if PARAM_NUM_PUBLISHQUEUES >= 3
PARAM_PUBLISHQUEUE_2 = 2,
#endif
#if PARAM_NUM_PUBLISHQUEUES >= 4
PARAM_PUBLISHQUEUE_3 = 3,
#endif
} param_publish_id_t;

#define PARAM_ADD_PUBLISH(paramname, queueid) \
param_publish_t __param_publish_##paramname##queueid = { \
.param = &paramname, \
.queue = queueid, \
}; \
__attribute__((section("param_publish"))) \
param_publish_t const * _param_publish_##paramname##queueid = & __param_publish_##paramname##queueid;

typedef bool (*param_shall_publish_t)(uint8_t queue);

void param_publish_periodic(void);
void param_publish_configure(param_publish_id_t queueid, uint16_t destination, uint16_t periodicity_ms, csp_prio_t csp_prio);
void param_publish_init(param_shall_publish_t criteria_cb);

#endif
Loading
Loading