Mastering Table‑Driven Parameter Management for Low‑Memory MCUs
This article explains the latest updates to a table‑driven parameter management library for MCU devices, covering unified parameter definitions, macro‑based registration, key‑value and non‑key‑value storage options, configurable trimming, macro and function interfaces, and provides detailed C code examples and serialization demos.
Introduction
The original version of the code performed serialization without considering the limited memory of MCU devices, resulting in large memory overhead and other issues. The new update addresses these problems by introducing a table‑driven approach that unifies parameter management.
Key Features
Unified table‑driven management of all parameters, including default, minimum, and maximum values.
Macro definitions enable rapid definition, registration, and management of parameters.
Support for defining ordinary parameters with various constraints:
No default value, no min/max limits.
Default value only.
Default value with min/max limits.
Parameters can be linked to existing variables such as global variables or struct members.
Support for basic type parameters and string parameters.
Serialization and deserialization allow saving/loading binary data on local storage devices.
Two storage modes:
Key‑value storage – maintains backward compatibility when parameters are added or removed.
Non‑key‑value storage – reduces serialized size for very small storage devices but loses compatibility unless new parameters are appended.
Multi‑step read/write to improve compatibility with low‑memory platforms.
Error‑handling callbacks trigger when a loaded parameter value is out of range, allowing the upper‑layer application to decide how to handle it (e.g., restore default).
Configurable feature trimming to adapt the library to chips with different memory capacities.
Both macro commands and function interfaces are provided for parameter operations, allowing developers to choose the most suitable method for a given scenario.
Code Example – Parameter Table Definition
PARAM_DEFINE_DAT (g_test, PARAM_INT16, 10);
PARAM_DEFINE_DAT_DEF (g_test_2, PARAM_UINT16, 20);
PARAM_DEFINE_DAT_RANGE (g_test_3, PARAM_DOUBLE, 3.15, -10, 10);
PARAM_DEFINE_STR_RANGE (g_test_str, 10, "abcdef", 5);
PARAM_DEFINE_DAT_RANGE (g_test_4, PARAM_INT8, 8, -10, 10);
PARAM_DEFINE_DAT_RANGE (g_test_5, PARAM_UINT32, 620, 500, 10000);
PARAM_DEFINE_DAT_RANGE (g_test_6, PARAM_UINT8, 45, 5, 100);
PARAM_DEFINE_DAT_RANGE (g_test_7, PARAM_INT64, 5, -542, 5450);
PARAM_DEFINE_BIND_DAT_RANGE(sg_tTest_test1, PARAM_UINT16, 20, 10, 2000); // bind variable
PARAM_DEFINE_BIND_DAT(sg_tTest_test2, PARAM_FLOAT); // bind variable
PARAM_DEFINE_BIND_STR_RANGE(sg_tTest_str, sizeof(sg_tTest.str), "const-zpc", 6);
ParamInfo_t sg_ParamTable[] = {
PARAM_ITEM_DAT(1, g_test, PARAM_ATTR_WR),
PARAM_ITEM_DAT_DEF(2, g_test_2, PARAM_ATTR_WR),
PARAM_ITEM_DAT_RANGE(3, g_test_3, PARAM_ATTR_WR),
PARAM_ITEM_STR_RANGE(4, g_test_str, PARAM_ATTR_WR),
PARAM_ITEM_DAT_RANGE(5, g_test_4, PARAM_ATTR_WR),
PARAM_ITEM_DAT_RANGE(6, g_test_5, PARAM_ATTR_WR),
PARAM_ITEM_DAT_RANGE(7, g_test_6, PARAM_ATTR_WR),
PARAM_ITEM_DAT_RANGE(8, g_test_7, PARAM_ATTR_READ), // read‑only
PARAM_ITEM_DAT_RANGE_BIND(9, sg_tTest_test1, sg_tTest.test1, PARAM_ATTR_WR),
PARAM_ITEM_DAT_BIND(10, sg_tTest_test2, sg_tTest.test2, PARAM_ATTR_WR),
PARAM_ITEM_STR_RANGE_BIND(11, sg_tTest_str, sg_tTest.str, PARAM_ATTR_WR),
};Using Macros to Operate Parameters
// Declare externs in a header
PARAM_EXTERN_DAT(g_test, PARAM_INT16);
PARAM_EXTERN_DAT(g_test_2, PARAM_UINT16);
PARAM_EXTERN_DAT(g_test_3, PARAM_DOUBLE);
PARAM_EXTERN_STR(g_test_str, 10);
PARAM_EXTERN_DAT(g_test_4, PARAM_INT8);
PARAM_EXTERN_DAT(g_test_5, PARAM_UINT32);
PARAM_EXTERN_DAT(g_test_6, PARAM_UINT8);
PARAM_EXTERN_DAT(g_test_7, PARAM_INT64);
int main() {
// Method 1 – use macro to set a new value
// Set g_test_6 to 50, ignore if out of range
PARAM_DAT_SET_NEW_VALUE(g_test_6, 50, PARAM_NONE);
// Set to 50, reset to default if out of range
PARAM_DAT_SET_NEW_VALUE(g_test_6, 50, PARAM_DEF);
// Set to 150, clamp to min/max if out of range
PARAM_DAT_SET_NEW_VALUE(g_test_6, 150, PARAM_MIN_MAX);
// Method 2 – assign directly then check range
g_test_6 = 50;
PARAM_DAT_CHECK_RANGE(g_test_6, PARAM_NONE);
g_test_6 = 50;
PARAM_DAT_CHECK_RANGE(g_test_6, PARAM_DEF);
g_test_6 = 150;
PARAM_DAT_CHECK_RANGE(g_test_6, PARAM_MIN_MAX);
}Using Functions to Operate Parameters
int main() {
PARAM_UINT16_T tmp;
// Method 1 – set new value via manager API
tmp = 50;
Param_SetNewValue(Param_FindParamByParamPtr(&sg_tParamManager, &g_test_u16), &tmp, PARAM_NONE);
tmp = 50;
Param_SetNewValue(Param_FindParamByParamPtr(&sg_tParamManager, &g_test_u16), &tmp, PARAM_DEF);
tmp = 150;
Param_SetNewValue(Param_FindParamByParamPtr(&sg_tParamManager, &g_test_u16), &tmp, PARAM_MIN_MAX);
// Method 2 – assign then check via manager API
g_test_6 = 50;
Param_CheckRange(Param_FindParamByParamPtr(&sg_tParamManager, &g_test_u16), PARAM_NONE);
g_test_6 = 50;
Param_CheckRange(Param_FindParamByParamPtr(&sg_tParamManager, &g_test_u16), PARAM_DEF);
g_test_6 = 150;
Param_CheckRange(Param_FindParamByParamPtr(&sg_tParamManager, &g_test_u16), PARAM_MIN_MAX);
}Serialization Demo Results
# Configuration supports up to 15 parameters – multi‑step read/save logs
load param:
read: [21] -> 12 0a 00 22 14 00 38 33 33 33 33 33 33 09 40 4a 61 62 63 64 65
read: [21] -> 66 00 00 00 00 51 08 64 6c 02 00 00 71 2d 88 05 00 00 00 00 00
save param:
save: [3] -> 12 0a 00
save: [3] -> 22 14 00
save: [9] -> 38 33 33 33 33 33 33 09 40
save: [11] -> 4a 61 62 63 64 65 66 00 00 00 00
save: [2] -> 51 08
save: [5] -> 64 6c 02 00 00
save: [2] -> 71 2d
save: [9] -> 88 05 00 00 00 00 00 00 00
# Key‑value serialization length: 44 bytes
"Key‑value serialization": [44] -> 12 0a 00 22 14 00 38 33 33 33 33 33 33 09 40 4a 61 62 63 64 65 66 00 00 00 00 51 08 64 6c 02 00 00 71 2d 88 05 00 00 00 00 00 00 00
"Raw serialization": [36] -> 50 00 14 00 33 33 33 33 33 33 09 40 67 5f 74 65 73 74 5f 36 00 00 00 6c 02 00 00 2d 05 00 00 00 00 00 00 00
# Configuration supports up to 256 parameters – key‑value length 52 bytes, raw length 36 bytes
... (similar output omitted for brevity) ...
# Configuration supports up to 4096 parameters – key‑value length 60 bytes, raw length 36 bytes
... (similar output omitted for brevity) ...Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
