|
Поиск по массиву в compile time на С |
|
|
|
May 3 2018, 11:54
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Есть массив регистров, ссылки на переменные с именами и некоторыми параметрами, для удобного доступа по разным интерфейсам и конфигурирования устройства. Допустим вот так объявленный, Код 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), ... Регистры адресуются по именам или по номерам. Имена достаточно постоянны, а номера могут изменяться в следующих версиях. В этом проблема, нельзя в коде просто взять ссылку на регистр по номеру regfile[n], номер может измениться. Искать по имени в compile time слишком сложно, средствами C и препроцессора не обойтись. По адресам переменных нельзя, они могут повторятся. Какие еще варианты? Сейчас думаю, генерировать из объявления массив макросов вида #define REG_hal_USART_baud_rate 0, но здесь тоже много проблем, надо как-то "спасать" недопустимые символы (точка и др.). Да можно обратится к переменным напрямую, но в некоторых случаях надо например сделать вывод значений, а в этом массиве регистров уже есть информация о том как это сделать для данного параметра. Не хочется дублировать одно и тоже в разным местах. Спасибо.
|
|
|
|
|
 |
Ответов
|
Aug 13 2018, 18:15
|
Гуру
     
Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493

|
А наоборот как ? Код typedef enum {t1, t2, t3 = (char) 100} myE; #pragma pack (1) struct My { myE e1; myE e2; myE e3; }; #pragma pack () int main() { cout << offsetof(My, e1) << endl; cout << offsetof(My, e2) << endl; } ...... e1 e2 e3 как были int так и остались. Компилятору по барабану все эти (char), он, как я понимаю, обязан уложиться в int и не более. Попросить его ограничиться char не могу, это compilator depended Можно было бы как Код enum class myE : char {t1, t2, t3, eMAX}; #pragma pack (1) struct My { myE e1; myE e2; myE e3; } my; #pragma pack () int main() { for (myE i = myE::t1; i < myE::eMAX; i++) Только вот так не получится , да и понятно почему (второе изображение) Выходит в С слишком опасно, в С++ слишком неудобно либо неэффективно. Решение есть, вот оно и ищется
Эскизы прикрепленных изображений
|
|
|
|
|
Aug 13 2018, 18:25
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
По-ходу я ошибся с явным указанием типа enum, у меня не работает Нужно это делать ключами компилятора: http://www.keil.com/support/man/docs/armcl...11640303038.htmКстати, у меня pragma pack вот так используется: Код #pragma pack(push, 1) .... #pragma pack(pop)
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Aug 13 2018, 18:43
|
Гуру
     
Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493

|
Цитата(Forger @ Aug 13 2018, 21:25)  По-ходу я ошибся с явным указанием типа enum, у меня не работает Нужно это делать ключами компилятора: http://www.keil.com/support/man/docs/armcl...11640303038.htmКстати, у меня pragma pack вот так используется: Код #pragma pack(push, 1) .... #pragma pack(pop) я думал, что могут быть такие ключи, но это еще меньше делать хочется. Если я делаю такие мерзости как явное приведение типов, то стараюсь писать static_cast <>, такая многословность в таких случаях в тему, при просмотре кода понимаю, что писав это понимал что делаю и чем чревато. А вот ключ компилятора ( если он есть) будем забыт сразу, в коде не видно. Признаюсь, особенно не мучался ранее стандартами, в голове засело, что enum это int, то ли книги так пишут, что непонятно. На самом деле enum это может и char и short и int быть, и , насколько помню, при сравнении такого enum с другим типом, имеющим неявное преобразование не будет даже warning.. А вот тут споткнулся
|
|
|
|
|
Aug 13 2018, 19:28
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(DASM @ Aug 13 2018, 21:43)  А вот тут споткнулся В "протокольных" делах enum не использую, но очень активно использую union: CODE static const struct { // Device answers uint8_t Ok; uint8_t Unknown; uint8_t WrongFirmware; uint8_t WriteError;
// Common commands uint8_t GetDeviceInfo; uint8_t DeviceReset; uint8_t BootloaderActivate;
// Bootloader commands uint8_t GetFirmwareFitures; uint8_t ChunkUpload; uint8_t PageWrite; uint8_t FirmwareVersionUpdate;
// Secret commands ..... } Command = { 0x00, 0x01, 0x02, 0x03, // Device answers 0xA0, 0xA1, 0xA2, // Common commands 0xE0, 0xE1, 0xE2, 0xE3, // Bootloader commands ...... // Secret commands };
.....
#if defined ( __CC_ARM ) // Arm Compiler v5 #pragma anon_unions #endif
#pragma pack(push, 1)
struct DeviceInfo { Settings::Version bootloaderVersion; Settings::Version firmwareVersion; Settings::Version hardwareVersion; Settings::SerialNumber serialNumber; ....... };
struct FirmwareFitures { uint32_t baseAddr; // Firmware Base Address uint32_t memorySize; // Flash memory size (including Bootloader and Firmware regions both) uint8_t chunkSize; uint16_t pageSize; };
struct FirmwareCheckZone { uint16_t crc16; uint16_t sizeKb; };
......
struct Report // 64 bytes { uint8_t command; union { uint8_t payLoad[REPORT_SIZE_BYTES - sizeof(command)];
struct DeviceInfo deviceInfo;
struct FirmwareFitures firmwareFitures;
struct { uint32_t addr; uint8_t data[FIRMWARE_CHUNK_SIZE_BYTES]; } chunk;
struct { uint32_t addr; } page;
............... }; };
#pragma pack(pop) Оба кода одинаково работают на Qt5 и под keil (v5 и v6), что очень удобно. Доп. ключей компиляции не использую. Использование const struct вместо define и enum (ну, не люблю их) позволяет мне делать код более читаемым. Разбор пакетов, в которых идут разношерстные данные благодаря union делает его очень компактным и также хорошо читаемым: CODE // в rxReport - уже лежит полученный пакет (USB hid)
if (rxReport.command == Command.GetDeviceInfo) { txReport.deviceInfo.bootloaderVersion = settings.getBootloaderVersion(); txReport.deviceInfo.firmwareVersion = settings.getFirmwareVersion(); txReport.deviceInfo.hardwareVersion = settings.getHardwareVersion(); txReport.deviceInfo.serialNumber = settings.getSerialNumber(); ......
txReport.command = Command.Ok; sendReport(txReport); return; }
if (rxReport.command == Command.GetFirmwareFitures) { txReport.firmwareFitures.baseAddr = FIRMWARE_BASE_ADDRESS; txReport.firmwareFitures.memorySize = FLASH_SIZE_KB * 1024UL; .... txReport.command = Command.Ok; sendReport(txReport); return; }
if (rxReport.command == Command.DeviceReset) { txReport.command = Command.Ok; sendReport(txReport); NVIC_SystemReset(); }
if (rxReport.command == Command.BootloaderActivate) { settings.killFirmware(); NVIC_SystemReset(); }
if (rxReport.command == Command.SerialNumberChange) { settings.setSerialNumber(rxReport.deviceInfo.serialNumber); // Other "deviceInfo" fields are ignored txReport.command = Command.Ok; sendReport(txReport); return; }
.....
Никаких адских массивов и массы магических чисел в качестве индесов для доступа к его содержимого. Через полгода/год открою этот код и сразу пойму, что тут происходит.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
Сообщений в этой теме
amaora Поиск по массиву в compile time на С May 3 2018, 11:54 Kabdim А зачем так сделано? Выглядит как кусок для внешне... May 3 2018, 12:09 Forger Масло-масляное.
Ваш некий реестр (я так понял по н... May 3 2018, 12:15 x736C Цитата(Forger @ May 3 2018, 15:15) зы. А ... May 3 2018, 14:01  Forger Цитата(x736C @ May 3 2018, 17:01) Как при... May 3 2018, 14:42 jcxz Цитата(Forger @ May 3 2018, 15:15) В свои... May 5 2018, 09:33  Forger Цитата(jcxz @ May 5 2018, 12:33) Лучше ра... May 5 2018, 10:26   jcxz Цитата(Forger @ May 5 2018, 13:26) К тому... May 5 2018, 11:02    Forger Цитата(jcxz @ May 5 2018, 14:02) Вобщем -... May 5 2018, 14:50 amaora Параметры не константные, все разные, есть настрой... May 3 2018, 13:16 Kabdim А точка в ваших определениях регистров всегда буде... May 3 2018, 13:40 amaora Функции доступа я тоже мог бы написать, но в этом ... May 5 2018, 08:15 amaora Вот так сделал
Кодcat regfile.c | sed -n ... Aug 11 2018, 18:54 Arlleex Цитата(amaora @ Aug 11 2018, 21:54) Вот т... Aug 12 2018, 07:00 amaora Ну, здесь я обычно не задаю вопросов по своей осно... Aug 12 2018, 16:52 Nixon Для доступа по индексу можно так сделать
Кодenum V... Aug 13 2018, 13:58 Forger Цитата(Nixon @ Aug 13 2018, 16:58) Для до... Aug 13 2018, 14:51 DASM Вот чтобы не плодить тем, возник вопрос. Есть стру... Aug 13 2018, 17:36 Forger Цитата(DASM @ Aug 13 2018, 20:11) ...
Пыт... Aug 13 2018, 17:39 Сергей Борщ QUOTE (DASM @ Aug 13 2018, 20:36) max_enu... Aug 13 2018, 18:31  DASM Цитата(Сергей Борщ @ Aug 13 2018, 21:31) ... Aug 13 2018, 18:37   Forger Цитата(DASM @ Aug 13 2018, 21:37) Но как ... Aug 13 2018, 18:39   Сергей Борщ QUOTE (DASM @ Aug 13 2018, 21:37) да оно ... Aug 13 2018, 19:47    DASM Цитата(Сергей Борщ @ Aug 13 2018, 22:47) ... Aug 13 2018, 20:08     Forger Цитата(DASM @ Aug 13 2018, 23:08) Можно с... Aug 13 2018, 20:17     Сергей Борщ QUOTE (DASM @ Aug 13 2018, 23:08) Выше вы... Aug 13 2018, 22:49      DASM Цитата(Сергей Борщ @ Aug 14 2018, 01:49) ... Aug 14 2018, 02:53      Nixon Цитата(Сергей Борщ @ Aug 14 2018, 01:49) ... Aug 14 2018, 06:14       DASM Цитата(Nixon @ Aug 14 2018, 09:14) Не обя... Aug 14 2018, 06:18        Nixon Цитата(DASM @ Aug 14 2018, 09:18) О, кста... Aug 14 2018, 06:24 DASM Гы, const struct а тут мы возвращаемся к вопросу и... Aug 13 2018, 19:39 Forger Цитата(DASM @ Aug 13 2018, 22:39) Гы, con... Aug 13 2018, 19:49 Nixon Может ещё кому полезно будет:
В анонимных структу... Aug 13 2018, 20:31 Forger Цитата(Nixon @ Aug 13 2018, 23:31) Наприм... Aug 13 2018, 20:37 Nixon Я без привязки к вашему примеру. Просто довольно п... Aug 13 2018, 20:49 Forger Цитата(Nixon @ Aug 13 2018, 23:49) Просто... Aug 13 2018, 20:51 DASM Вот нашел ответ, как удобно пользовать enum class.... Aug 14 2018, 05:53 Kabdim По факту тип указанный в энуме, года 3 назад работ... Aug 14 2018, 06:32 DASM Да, лучше. Но пока не знал об этом - много писанин... Aug 14 2018, 06:34 Kabdim Цитата(DASM @ Aug 14 2018, 09:34) "3... Aug 14 2018, 06:49 Nixon В стандарте то стандарте, но не совсем "С... Aug 14 2018, 06:39 DASM Цитата(Nixon @ Aug 14 2018, 09:39) В стан... Aug 14 2018, 07:10  Kabdim Цитата(DASM @ Aug 14 2018, 10:10) это как... Aug 14 2018, 07:17 DASM Цитатаtypedef enum { tst, tst2, tst3 } test;
#pra... Aug 16 2018, 06:32 Kabdim Цитата(DASM @ Aug 16 2018, 09:32) А что т... Aug 16 2018, 14:29  DASM Цитата(Kabdim @ Aug 16 2018, 17:29) А чег... Aug 16 2018, 14:41   Forger После sizeof ( некого enum ), недалеко и до sizeof... Aug 16 2018, 14:56    DASM Цитата(Forger @ Aug 16 2018, 17:56) После... Aug 16 2018, 15:09     Forger Цитата(DASM @ Aug 16 2018, 18:09) А все ж... Aug 16 2018, 15:13   Kabdim Цитата(DASM @ Aug 16 2018, 17:41) Просто ... Aug 17 2018, 10:39    Arlleex Цитата(Kabdim @ Aug 17 2018, 14:39) Как э... Aug 17 2018, 10:54    DASM Цитата(Kabdim @ Aug 17 2018, 13:39) Как э... Aug 17 2018, 12:04     Forger Цитата(DASM @ Aug 17 2018, 15:04) offseto... Aug 17 2018, 12:23     Kabdim Применительно к этой ситуации, как раз Кейл - непр... Aug 17 2018, 12:45 sigmaN Извиняюсь, если это уже предлагали(не читал все со... Aug 17 2018, 08:08 Kabdim Я не вижу. Вопрос был DASM'у цитата к которой ... Aug 17 2018, 11:51 sigmaN From Standard C++ 7.2/5:
ЦитатаThe underlying type... Aug 19 2018, 06:25 DASM Да ладно, фиг с ним. Aug 19 2018, 20:41
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|