Ошибка IDE: size of variable is too large

Пытаюсь собрать код с большим массивом вида:

PROGMEM const uint16_t array[] = { };

void Func(uint16_t* data) {
uint16_t *ptr = data; }

кол-во элементов array 23040. При таких размерах IDE пасует с ошибкой ‘size of variable is too large’.

Как бы тут правильно код организовать, чтобы не морочиться разбиением array на несколько массивов и отслеживанием переключения между ними?

подарить калькулятор? - чтобы вы смогли умножить 23040 на 2 и сравнить с размером флеша у ардуино уно-нано…

никак. Разбиение на несколько массивов не поможет

Не смущает что это 45кб? У тебя памяти в мк сколько?

не смущает, что у меня mega?

почему? если они гарантированно подряд будут идти, то указатель спокойно по ним будет бегать.
вопрос в том, как компилятору сказать, что их строго последовательно нужно разместить.

а это было где-то указано?

В меге, скорее всего, проблема в том что массив пересек границу 16битных адресов. Чтобы использовать флеш выше 64к, нужны отдельные ухищрения

это будет “гавно-код” высшего уровня, сорри

1 лайк

Если ставлю массив вдвое меньше, то проблем нет. При этом размер суммарного кода 72948.
Скорей всего это проблема на уровне IDE.

между “не сделать ничего” и “говнокод” - выбираю второе.

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

IDE не компилирует, оно не виновато.
Я бы попробовал двумерный массив объявить - он в линеечку должен вытянуться.

хм, думаешь дело в размере индекса?

Да, хоть Гига, это не от этого зависит.

Максимальный размер массива (именно размер, а не количество элементов) задаётся константой PTRDIFF_MAX. Попробуйте на своей Меге вывести её значение в монитор порта и полюбуйтесь на него.

void setup(void) {
   Serial.begin(9600);
   Serial.printl(PTRDIFF_MAX);
}

void loop(void) {}

Там ведь по стандарту как. Тип size_t вроде как беззнаковый, но тип ptrdiff_t - знаковый. Отсюда ноги и растут.

  1. Получается для word предел в 16384. Полезная инфа.
    N-мерность тут не поможет. Придется варпер писать.

насколько я понял, PTRDIFF_MAX это всегда максимальный размер знакового int на платформе. То есть на Гиге (есть такая ардуина на основе STM32H7 :slight_smile: - это будет 2 миллиарда

@ae485
возьмите любую 32-битную ардуину - ЕСП32 или СТМ32 - там нет этого ограничения (точнее есть, но вам точно хватит :slight_smile:
Заодно и с ПРОГМЕМ не надо будет связываться. Вообще, с появлением доступных ЕСП32 и СТМ32 я не понимаю, зачем разрабатывать серьезные проекты на АВР. 8битные платы очень устарели

2 лайка

Нет, просто оно бы одной кучкой легло. В теории.
Но, раз ЕП уже пояснил про тип указателя, то совет неактуален.

Ну вот и ответ: часть массива лежит за пределами 64к блока, адресуемого int*.
Здесь нужен far указатель (точно не помню, как он записывается, но дальше можно поиском).

перешел недавно с Nano на Мегу, думал хватит )

да, надо будет вспомнить синтаксис. Со времен TurboC не приходилось пользоваться.

поиском сразу нашел как засовывать бинарники принудительно выше 64к:

extern` `unsigned ` `char` `_binary_a9x160_lcd_bin_start;
pgm_get_far_address(_binary_a9x160_lcd_start)

но нужно в полуручном режиме линковать в обход IDE.
в целом выглядит так, словно himem в мегу добавили, а IDE под это не допилили.

Неверно поняли. Это максимальное значение типа ptrdiff_t, который часто совпадает со знаковым int, но совершенно не обязательно.

Все уже давно пофиксили.

const char far_away[] PROGMEM1 = "Hello from far away!\n"; // (64  - 128kB)
const char far_far_away[] PROGMEM2 = "Hello from far, far away!\n"; // (128 - 192kB)
const char far_far_far_away[] PROGMEM3 = "Hello from far, far, far away!\n"; // (192 - 256kB)

void print_progmem()
{
  uint8_t i;
  char c;

  // Print out far_away
  for(i = 0; i < sizeof(far_away); i++)
  {
    c = pgm_read_byte_far(pgm_get_far_address(far_away) + i);
    Serial.write(c);
  }

  // Print out far_far_away
  for(i = 0; i < sizeof(far_far_away); i++)
  {
    c = pgm_read_byte_far(pgm_get_far_address(far_far_away) + i);
    Serial.write(c);
  }
  // Print out far_far_far_away
  for(i = 0; i < sizeof(far_far_far_away); i++)
  {
    c = pgm_read_byte_far(pgm_get_far_address(far_far_far_away) + i);
    Serial.write(c);
  }
}