Где хранить структуру, используемую для инициализации драйвера

Я делаю небольшой проект с платой ESP32. При инициализации драйвера функциям инициализации передается несколько структур. Я знаю, что есть два способа хранения таких структур:

  1. Хранение структур в куче (с помощью calloc или malloc)
adc_continuous_config_t cfg = calloc(1, sizeof(adc_continuous_config_t));

cfg->sample_freq_hz = 4500;
cfg->conv_mode = ADC_CONV_SINGLE_UNIT_1;
cfg->format = ADC_DIGI_OUTPUT_FORMAT_TYPE;

adc_continuous_config(*handle, cfg);
free(cfg);
  1. Хранение структур в стеке
adc_continuous_config_t cfg = {
    .sample_freq_hz = 4500,
    .conv_mode      = ADC_CONV_SINGLE_UNIT_1,
    .format         = ADC_DIGI_OUTPUT_FORMAT_TYPE1,
};

adc_continuous_config(*handle, &cfg)

Мне интересно, какой подход приветствуется.

, 👍1

Обсуждение

Это зависит от нескольких деталей, например: Каков запрошенный срок жизни данных? Будут ли данные повторно использоваться позже? Значения структуры известны во время компиляции? И, вероятно, еще что-то. Поэтому на этот вопрос нельзя ответить в целом., @the busybee

Я думаю, что структура используется только для инициализации драйвера, которая происходит только один раз за срок службы машины, что означает, что она не будет использоваться повторно до перезагрузки. Все значения структуры — это просто предопределенные константы, поэтому они известны во время компиляции., @Yiyang Yan

Затем воспользуйтесь решением Эдгара, поместив структуру во флэш-память., @the busybee


1 ответ


2

Похоже, вы инициализируете эту структуру константами. В таком случае, Я бы не использовал ни кучу, ни стек, а выбрал третий вариант: раздел программы «данные только для чтения». В глобальном масштабе:

const adc_continuous_config_t cfg = {
    .sample_freq_hz = 4500,
    .conv_mode      = ADC_CONV_SINGLE_UNIT_1,
    .format         = ADC_DIGI_OUTPUT_FORMAT_TYPE1,
};

Обоснование: константы, которые вы используете для заполнения структуры, должны быть хранится где-то во флэш-памяти, когда программа не запущена. Хотя Я не знаю подробностей машинного языка ESP32, кажется на мой взгляд, у компилятора есть только два варианта компиляции кода вашего примера. Это мог бы сказать:

  • загрузить регистр ЦП с непосредственным значением 4500
  • сохраните этот регистр по адресу cfg->sample_freq_hz
  • загрузить регистр ЦП с непосредственным значением ADC_CONV_SINGLE_UNIT_1
  • и т. д.

Затем значения сохраняются как непосредственные операнды машины инструкции. Другой вариант — хранить анонимную версию инициализированная структура в разделе данных программы, доступном только для чтения, и выполните memcpy() для инициализации выделенного пространства во время выполнения.

Если вместо этого вы сохраните инициализированную структуру как глобальную константу, она перейдет прямо в раздел данных программы, доступный только для чтения (как в вторую стратегию компилятора), и вы будете использовать ее оттуда. Никаких дополнительных нужна копия. Никаких дополнительных машинных инструкций для инициализации пространства. выделяется в куче или стеке.

Предостережение: я предполагаю, что adc_continous_config() ожидает второго параметр должен иметь тип «указатель на данные const». Если оно этого ожидает быть указателем на изменяемые данные, то это не сработает.

,