This is for an embedded application that runs at a low level on a uC. Another part of the system requires parameters to be set and the local uC needs to maintain a list of parameters. Each parameter consists of an 8 bit ID and an 8 bit value. The ID's begin at 0x70 due to memory limitations at the other end.
In order to keep the memory usage as low as possible I have implemented the parameter store as an array containing the IDs and Values for all the writable parameters. There is then an enumerated list of these parameters in the header file to allow other parts of the application to access the parameters.
Is there any way to ensure that the enum list and the array of parameters have the same entries in the same order? I have documented the code fairly thoroughly (not all included in the extracts) but I would like to put in some form of check at compile time to ensure that the list and array match up.
Another thing I'm not sure of is if this is the most efficient way of implementing this. I need to be able to iterate through the parameters in order to transmit them to the other part of the system and I need to use as little memory as possible.
From parameters.h
:
/*******************************************************************************/
/* IDs for all parameters must be defined */
/* Defaults only need to be defined for rut-time writable parameters */
/* All parameters must have an ID define */
/* Writable parameters must also have: */
/* * DefaultValue define */
/* * Entry in ParamIndex */
/* * Initialesed default entry in Parameters (contained in C file) */
/* * If min and max values are not 0x00 and 0xFF then define those too */
/*******************************************************************************/
// Parameter IDs - All parameters need this defining
#define Param_ActualTemp_ID 0xE0
#define Param_OperationMode_ID 0xE1
#define Param_MaintenanceModePID0_ID 0xE5
#define Param_MaintenanceModePID1_ID 0xE6
#define Param_FirmwareVersionL_ID 0xEB
#define Param_FirmwareVersionH_ID 0xEC
#define Param_SerialNumberL_ID 0xED
#define Param_SerialNumberH_ID 0xEE
#define Param_SerialNumberHH_ID 0xEF
#define Param_MaxTemperature_ID 0xFC
#define Param_NULL_ID 0xFF
// Parameter Default Values - All writable parameters need this defining
#define Param_NULL_DefaultValue 0xFF
#define Param_OperationMode_DefaultValue 0
#define Param_MaintenanceModePID0_DefaultValue 0xFF
#define Param_MaintenanceModePID1_DefaultValue 0xFF
#define Param_MaxTemperature_DefaultValue 0x54
typedef struct
{
const uint8 id;
uint8 value;
} PARAMETER;
// Parameter Index, any writable parameters need an entry here
// Used as array index for parameters[], do not edit existing values
typedef enum
{
Param_NULL = 0,
Param_OperationMode,
Param_MaintenanceModePID0,
Param_MaintenanceModePID1,
Param_MaxTemperature,
/* Additional values must be entered above this line */
Param_NUMBER_OF_IMPLEMENTED_PARAMS
} ParamIndex;
extern PARAMETER parameters[];
From parameters.c
:
PARAMETER parameters[] = {
{ .id = Param_NULL_ID, .value = Param_NULL_DefaultValue},
{ .id = Param_OperationMode_ID, .value = Param_OperationMode_DefaultValue},
{ .id = Param_MaintenanceModePID0_ID, .value = Param_MaintenanceModePID0_DefaultValue},
{ .id = Param_MaintenanceModePID1_ID, .value = Param_MaintenanceModePID1_DefaultValue},
{ .id = Param_MaxTemperature_ID, .value = Param_MaxTemperature_DefaultValue}
};
You are on the right track with the Param_NUMBER_OF_IMPLEMENTED_PARAMS
. Unfortunately you cannot use this as an array size, because that only guarantees that the array doesn't have more initializers than the enum. It does not protect against the array having too few initializers.
The way to ensure this is to make a static assertion of the enum size versus the array size. Keep the array declaration as PARAMETER parameters[]
and then do
_Static_assert(Param_NUMBER_OF_IMPLEMENTED_PARAMS == sizeof(parameters)/sizeof(*parameters),
"Array initializer list does not match enum");
The standard keyword _Static_assert
is however only available in C11, and the standard macro static_assert
is only available in C11 and C++. On older compilers, you will have to invent it yourself. For example:
#define STATIC_ASSERT(expr) {typedef uint8_t S_ASSERT[(expr) ? 1 : 0];}
This will give a cryptic "cannot declare an array with size zero" compiler error if the assert fails.
Ordering can be ensured by using designated initializers for the array items:
PARAMETER parameters[] = {
[Param_NULL_DefaultValue] = { .id = Param_NULL_ID, .value = Param_NULL_DefaultValue},
...
Designated initializers does not prevent duplicates, but in case of duplicate entries only the last one will be used (and you typically get a compiler warning). Such duplicate entries will not affect the array size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With