• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

заставить esp хранить все константы во флеш без макрос F()

Junkie

Member
Подскажите возможно ли это? чтоб сэкономить ОЗУ оборачиваю все строчки во всех функция в макрос F, можно ли сделать так чтобы автоматически esp не загружал константы из флеша в озу?
 

Junkie

Member
при старте все константы копируются в озу, даже если ты эту функцию вызовешь один раз и в ней константы, они будут висеть в памяти всегда
 

enjoynering

Well-known member
У вас смешались кони и люди.

Только глобальные переменные остаются в памяти навсегда. Локальные переменные (те которые объявленный внутри функций) уничтожаются после завершения работы функций. Если очень хочется чтоб переменная не уничтожалась - используем static.

Костанты - это переменные которые в коде никогда не меняются. Держать их постоянно в памяти не имеет смысла. Экономим память так - задаем костанты через #define. Например:

Код:
#define MUNBER_PI 3.14

Если это не изменяемый массив/array (например шрифт для экрана) то используем PROGMEM.

Подробнее ищем в гугл по ключевым словам.
 

Junkie

Member
проверь сам занимаемое озу, если внутри функции объявишь константой длинный массив символов то свободная память уменьшиться
 

nikolz

Well-known member
[1. Сохраняйте строки в памяти Flash]

(1) Разместите некоторые строки во flash, особенно длинные, такие как запросы HTML и шаблоны ответов. Например, строка изначально была определена так:

#define test_string "hello world"

Вы можете определить эту строку следующим способом, и тогда она будет размещена во flash:

static const char test_string[] ICACHE_RODATA_ATTR = "hello world";

(2) Когда определяете строковые константы с ICACHE_RODATA_ATTR, пользователи должны получать доступ к её содержимому операциями чтения, выровненными по размеру слова (байтовый адрес доступа должен нацело делиться на 4). Так как данные во flash должны быть прочитаны порциями по 4 байта, пользователи должны определить макрос для получения выровненной длины строки:

#define GET_ALIGN_STRING_LEN(str) ((strlen(str) + 3) & ~3)

Когда используются строки, выделите динамически новый объект массива, чтобы прочитать туда данные строки из flash. Затем используйте os_memcpy API для копирования содержимого строки:

unsigned int str_len = GET_ALIGN_STRING_LEN(test_string);
char *tmp_string = (char *)os_malloc(str_len);
os_memcpy(tmp_string, test_string, str_len);

(3) В коде приложения используйте test_string. Это также решит проблему исключений, вызванных приложениями при не выровненном доступе с содержимому памяти flash, одновременно снижая объем RAM, занимаемый Вашим приложением.

(4) Когда код пользователя использует метод получения данных, описанный выше, то нужно освобождать память с помощью вызова:

os_free(tmp_string);

Имейте в виду, что если этого не делать, то постоянные выделения памяти уменьшат её количество в куче, и для функционала ядра может не хватить памяти, что приведет к неправильной работе и отказу вызовов API.

[2. Сохраняйте данные констант во flash]

(1) Напрямую размещайте массивы unit32 в памяти flash. Пример:

const uint32 array[4] ICACHE_RODATA_ATTR =
{
0x11111111, 0x22222222, 0x33333333, 0x44444444
};

Пользователи могут напрямую использовать ячейки этого массива без каких-либо проблем (array[0], и т. п.).

(2) Однако доступы на чтение к массивам unit8 и unit16 должны быть выровнены по границе 4 байта. Пример:

const uint8 array[7] ICACHE_RODATA_ATTR = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

Если Вам нужно прочитать элементы в массиве char по байтам, попробуйте программно читать в память RAM элементы порциями по 4 байта, и затем читайте каждый байт по его смещению 0..3.. Прямой доступ к отдельным элементам байтового массива этого примера (array[1], и т. п.) приведет к отказу приложения.

(3) Для структур памяти общим принципом доступа к ним является выделение достаточного количества памяти в RAM, которое больше размера памяти структуры, которую Вы хотите прочитать. Читайте данные из порциями, размер которых делится на 4 байта, и сохраняйте их в RAM. Используйте указатель на объект в коде как обычно, что показано в предыдущем примере. Просто измените код для чтения структуры вместо чтения массива.

[3. Сохраняйте строки отладки в памяти flash]

Строки, выводимые на печать встроенной функцией printf, по умолчанию находятся в RAM. Если Вам не нужно часто печатать в лог строки отладки, или если эти строки слишком длинные, то используйте оптимизированное os_printf API для загрузки строк отладки во flash вместо RAM.

[4. Старайтесь избегать глобальных переменных]

Глобальные переменные часто занимают излишнее место, поскольку используются они скорее всего не во все время жизни приложения. Espressif предоставляет API для динамического выделения памяти, что можно применять для снижения использования глобальных переменных. Для программирования на основе событий всегда используйте os_malloc и os_free для динамического выделения места в памяти, когда это необходимо. Однако разработчики не рекомендуют использовать частое выделение/освобождение памяти порциями разного размера.
 
Сверху Снизу