Код
typedef struct {
const char *sym;
const char *fmt;
int mode;
union {
float *f;
int *i;
}
link;
void (* proc) (const void *reg, void *lval, const void *rval);
}
reg_t;
#define REG_E(link, extra, unit, fmt, mode, proc) { #link extra "\0" unit, fmt, mode, \
{ (void *) &link }, (void *) proc }
#define REG(link, unit, fmt, mode, proc) REG_E(link, "", unit, fmt, mode, proc)
const reg_t regfile[] = {
REG(hal.USART_baud_rate, "", "%i", REG_CONFIG, NULL),
REG(hal.PWM_freq_hz, "Hz", "%i", REG_CONFIG, NULL),
REG(hal.PWM_dead_time_ns, "ns", "%i", REG_CONFIG, NULL),
REG(hal.ADC_reference_voltage, "V", "%3f", REG_CONFIG, NULL),
REG(hal.ADC_current_shunt_resistance, "Ohm", "%4e", REG_CONFIG, NULL),
...
REG(pm.probe_speed_ramp, "rad/s", "%2f", REG_CONFIG, NULL),
REG_E(pm.probe_speed_ramp, "_rpm", "rpm", "%2f", REG_NORMAL, ®_proc_rpm),
...
const char *sym;
const char *fmt;
int mode;
union {
float *f;
int *i;
}
link;
void (* proc) (const void *reg, void *lval, const void *rval);
}
reg_t;
#define REG_E(link, extra, unit, fmt, mode, proc) { #link extra "\0" unit, fmt, mode, \
{ (void *) &link }, (void *) proc }
#define REG(link, unit, fmt, mode, proc) REG_E(link, "", unit, fmt, mode, proc)
const reg_t regfile[] = {
REG(hal.USART_baud_rate, "", "%i", REG_CONFIG, NULL),
REG(hal.PWM_freq_hz, "Hz", "%i", REG_CONFIG, NULL),
REG(hal.PWM_dead_time_ns, "ns", "%i", REG_CONFIG, NULL),
REG(hal.ADC_reference_voltage, "V", "%3f", REG_CONFIG, NULL),
REG(hal.ADC_current_shunt_resistance, "Ohm", "%4e", REG_CONFIG, NULL),
...
REG(pm.probe_speed_ramp, "rad/s", "%2f", REG_CONFIG, NULL),
REG_E(pm.probe_speed_ramp, "_rpm", "rpm", "%2f", REG_NORMAL, ®_proc_rpm),
...
Регистры адресуются по именам или по номерам. Имена достаточно постоянны, а номера могут изменяться в следующих версиях. В этом проблема, нельзя в коде просто взять ссылку на регистр по номеру regfile[n], номер может измениться. Искать по имени в compile time слишком сложно, средствами C и препроцессора не обойтись. По адресам переменных нельзя, они могут повторятся. Какие еще варианты?
Сейчас думаю, генерировать из объявления массив макросов вида #define REG_hal_USART_baud_rate 0, но здесь тоже много проблем, надо как-то "спасать" недопустимые символы (точка и др.).
Да можно обратится к переменным напрямую, но в некоторых случаях надо например сделать вывод значений, а в этом массиве регистров уже есть информация о том как это сделать для данного параметра. Не хочется дублировать одно и тоже в разным местах.
Спасибо.