tathagata 0 18 августа, 2023 Опубликовано 18 августа, 2023 (изменено) · Жалоба MDR32F1QI. Программа использует калибровочную таблицу переменной длины, под которую отводится страница памяти во Flash-области. В выделенной под таблицу секции памяти необходимо проинициализировать нулевыми значениями переменную — текущую длину таблицы, а так же сами данные. Соответствующий участок C-кода выглядит так: // Максимальное количество записей в таблице #define MAX_TABLE_SIZE 500 // Структура записи в таблице typedef struct { uint32_t value; uint32_t corr; } record_t; // Текущее количество записей в таблице const volatile size_t table_sz __attribute__((section(".table"))) = 0; // Массив стуктур const volatile record_t table[MAX_TABLE_SIZE] __attribute__((section(".table"))) = { {0, 0} }; Далее привожу соответствующий scatter-файл: LR_IROM1 0x00000000 0x00012000 { ; load region size_region ER_IROM1 0x00000000 0x00010000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00008000 { ; RW data .ANY (+RW +ZI) } RW_IRAM2 0x20100000 0x00004000 { mdr32f9qx_eeprom.o eeprom.o (+RO) .ANY (+RW +ZI) } } } LR_IROM2 0x00013000 0x00001000 { ; load region size_region ER_IROM2 0x00013000 0x00001000 { ; * (.table) } } Компилирую и собираю (ARMCC 5.06), после чего с помощью objdump смотрю выходной файл. И здесь начинается волшебство: Содержимое раздела ER_IROM2: 13000 01ff01ff 01ff01ff 01ff01ff 01ff01ff ................ 13010 01ff01ff 01ff01ff 01ff01ff 01ff01b3 ................ Далее, пытаюсь уменьшить длину массива в объявлении (MAX_TABLE_SIZE = 20). И, о чудо! Содержимое раздела ER_IROM2: 13000 00000000 00000000 00000000 00000000 ................ 13010 00000000 00000000 00000000 00000000 ................ 13020 00000000 00000000 00000000 00000000 ................ 13030 00000000 00000000 00000000 00000000 ................ 13040 00000000 00000000 00000000 00000000 ................ 13050 00000000 00000000 00000000 00000000 ................ 13060 00000000 00000000 00000000 00000000 ................ 13070 00000000 00000000 00000000 00000000 ................ 13080 00000000 00000000 00000000 00000000 ................ 13090 00000000 00000000 00000000 00000000 ................ 130a0 00000000 .... Опытным путем обнаружил, что максимальное работающее значение MAX_TABLE_SIZE равно 36. Тогда и переменная, отвечающая за текущую длину массива, и сам массив аккуратно в зануленном виде появляются в соответствующей секции. Иначе — мусор, подобный тому, что выше. Например, при MAX_TABLE_SIZE = 37 соответствующая секция выглядит так (вообще одно значение): Содержимое раздела ER_IROM2: 13000 01ff012d ...- Помогите разобраться с этим "волшебством". Сразу скажу, что при использовании GCC и ld никаких проблем не возникает. Массив и переменная в аккурат инициализируются в том количестве, какое задано. А вот с Keil у меня засада. Но необходимо делать код рабочим под оба компилятора. Есть, конечно, еще workaround: массив ведь можно заменить указателем относительно адреса переменной —- текущей его длины (что и было сделано в самом первоначальной версии), причем инициализация нулями его элементов необязательна — нулевая начальная длина (в соответствующей переменной) вполне достаточна для правильной работы программы. Но последующие считывание и запись в массив будут происходить тоже через смещения указателя относительно базового адреса переменной. Это, как мне кажется, не совсем удобно. Тем более, когда в GCC и ld все прекрасно работает. Посему в силу моего небольшого опыта прошу помочь разобраться с этой странной проблемой в Keil. Заранее спасибо за помощь. Изменено 18 августа, 2023 пользователем tathagata Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 18 августа, 2023 Опубликовано 18 августа, 2023 · Жалоба 14 минут назад, tathagata сказал: const volatile record_t в чем прикол делать таблицу констант волатильной? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 18 августа, 2023 Опубликовано 18 августа, 2023 · Жалоба 5 минут назад, AlexRayne сказал: в чем прикол делать таблицу констант волатильной? Если она в процессе работы перешивается, например. Чтобы компилятор не подумал, что там всегда нули как во время компиляции и не соптимизировал доступ к ней. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 18 августа, 2023 Опубликовано 18 августа, 2023 · Жалоба Вот наткнулся на доп. команду линкера: --keep=''*.o(mysection)'' https://habr.com/ru/articles/685028/ Проверил ваш код в компиляторе/линкере v6.19, все прекрасно работает и размещается где нужно, а вот если убрать из misc опций вот эту строку --keep=''*.o(tables)'' (на картинке пример), Spoiler то начинает сразу ругаться: Quote warning: L6329W: Pattern *.o(tables) only matches removed unused sections. конечно, дело в том, что в основном коде нигде не используются эти массивы и линкер просто из вырезал, эта команда помогает их сохранить если использовать их в коде явно, но они никуда не деваются и эта команда --keep не требуется Подобное полезно для размещения неких структур, доступ к которым производится косвенно, по конкретным адресам без указания названий этих структур, иначе линкер молча их вырежет и вы получите по этим адресам мусор. Например, нужно разместить образ некой прошивки некой плис по фиксированному адресу. Полезная фича )) для проверки использовал такое содержимое скрипта линкера: LR_IROM1 0x08000000 0x80000 { ; load region size_region ER_IROM1 0x08000000 0x70000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } ER_IROM2 0x08070000 0x1000 { ; *.o (tables) } RW_IRAM1 0x20000000 0x00010000 { ; RW data .ANY (+RW +ZI) } } ну и ваш код: // Текущее количество записей в таблице const volatile size_t table_sz __attribute__((section("tables"))) = 0; // Массив стуктур const volatile record_t table[MAX_TABLE_SIZE] __attribute__((section("tables"))) = { {0, 0} }; Ну и выписка из map файла: Quote table_sz 0x08070000 Data 4 application.o(tables) table 0x08070004 Data 4000 application.o(tables) 26 minutes ago, AlexRayne said: в чем прикол делать таблицу констант волатильной? Попробовал из любопытства убрать volatile из объявления: // Текущее количество записей в таблице const size_t table_sz __attribute__((section("tables"))) = 0; // Массив стуктур const record_t table[MAX_TABLE_SIZE] __attribute__((section("tables"))) = { {0, 0} }; и линкер тут же начал ругаться на отсутствующую секцию: Quote Warning: L6319W: Ignoring --keep command. Cannot find section *.o(tables). warning: L6314W: No section matches pattern *.o(tables). по ходу volatile обладает некой "магией" 😉 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tathagata 0 18 августа, 2023 Опубликовано 18 августа, 2023 · Жалоба Эксперименты показали, что ARMCLANG (6.18 в моем случае) правильно размещает массив на Flash. В то время как ARMCC (5.06), на котором и строился проект, имеет такой неприятный баг. Выбор компилятора в моем случае осложняется тем, что при использовании миландровских библиотек ARMCLANG при сборке выдает много странных ошибок, которые я отношу на совесть разработчиков пакета драйверов для Milandr. Для экспериментов собирать пришлось, в качестве устройства выбрав в обоих случаях стандартный ARMCM0P (ARM Cortex M0 plus). Если кто-то подскажет рабочее решение для увы устаревшего ARMCC v5.06, буду очень признателен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 18 августа, 2023 Опубликовано 18 августа, 2023 · Жалоба 25 minutes ago, tathagata said: Если кто-то подскажет рабочее решение для увы устаревшего ARMCC v5.06, буду очень признателен. Или писать разрабам в миландр чтобы переделали свои либы под нормальные компиляторы или делать это вручную, самостоятельно Есть третий вариант - вообще не пользоваться либами миландра, а максимум лишь их h-файлами (регистры и структуры). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 83 18 августа, 2023 Опубликовано 18 августа, 2023 · Жалоба 3 часа назад, tathagata сказал: MDR32F1QI А это же 1986ВЕ1, а он Cortex-M1(или 2? не помню - ядро ARM Cortex для ПЛИС) Вот, нашел, собирал его проекты как Cortex-M1. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 18 августа, 2023 Опубликовано 18 августа, 2023 (изменено) · Жалоба 6 часов назад, Forger сказал: по ходу volatile обладает некой "магией" 😉 А ваш код вобще использует этот массив? или функции его использовашие выброшены? Куда он вообще положил вашу таблицу? видимо не в секцию `tables` а во text? Изменено 18 августа, 2023 пользователем AlexRayne Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться