Пишу на си в avr studio. В eeprom полно переменных, но одна из них должна четко находится по адресу 0х00 (т.к. к ней обращается bootloader со своей секции). Переменная uint8_t (в 1 байт), но как ее разместить четко по этому адресу, чтобы не заморачиватся больше.
Думал об ассемблерных вставках, почитал инет, но прояснилось не очень...
Заранее благодарен.
Адреса вроде как назначаются в порядке описания переменных.
Если необходима жесткая привязка по адресам, то описывайте функции чтения-записи еепром вручную.
Если в AVR Studio, значит компилятор - AVR GCC. А коли так, то можно действовать именно так, как сказали выше - писать руками. С одной поправкой - работа с EEPROM уже описана в avr/eeprom.h
AVR GCC, в отличие от IAR, не поддерживает прозрачную запись в EEPROM - значения писать туда (читать из) надо руками с помощью функций eeprom_read_xxx / eeprom_write_xxx. А всякие спецификаторы типа EEMEM в этом случае - не более чем синтаксический сахар; переменную, объявленную со спецификатором EEMEM, все равно нельзя использовать в выражении напрямую.
Так что можно не париться и, если нужно четкое распределение по адресам, делать так:
Можно, конечно, заморочиться и создать в конфиге линкера специальную секцию для нулевого адреса EEPROM (и потом прописать ее для переменной в __attribute__(...) ), но, IMHO, оно того не стоит.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Спасибо YS. Я собственно так и думаю. Просто чего меня смущает: в этом случае компилятор сам раскидывает переменные в адресном пространстве eeprom. Логично, что он начнет с 0x00. Строка
не сотрет переменную по адресу 0х00? Конечно есть предположение, что компилятор увидев эту запись начнет писать переменные с адреса 0х01. Но я в этом далеко не уверен.
есть предположение, что компилятор увидев эту запись начнет писать переменные с адреса 0х01
Нет, не начнет. Для него такая "переменная" ничего не значит.
Да, когда переменные объявляются как переменные со спецификатором EEMEM, компилятор сам раскидывает адреса. Я к тому, что все переменные я бы заменил на такие дефайны, и отслеживал бы их пересечение/непересечение руками. Да, слегка неудобно, но в EEPROM и не бывает десятков переменных...
Если переменных все же много, и отслеживать их положение руками страсть как не хочется (и играться с линкером тоже), можно исхитриться так: завести структуру со всеми необходимыми переменными, создать указатель на нее и положить ее в EEPROM. Поля структуры всегда хранятся в порядке объявления, так что тут неожиданностей 100% не будет; при этом компилятор раскидает адреса сам.
Поиграть с линкером я как раз не против. Только никогда этого не делал. Почитал пару статеек в инете, чего то прояснилось, но явно не все.
Мне надо создать отдельную секцию в секции .eeprom. Правильно?
Что я для этого должен сделать: записать туда, куда показано на прикрепленном рисунке примерно следующее
Это укажет на то, что eeprom начинается с 1-го адреса, а не с нулевого. Т.е. ВСЕ переменные EEMEM расположатся, начиная с 1-го адреса. Стандартные функции eeprom_*_*() будут работать корректно:
char EEMEM a, b, c,...
eeprom_write_byte(&a, 0x55);
Для работы с неиспользуемым нулевым адресом нужно явно указать его при вызове этих функций. Кроме того, если нужна генерация .eep файла с инициализированными переменными EEMEM, то для obj-copy надо указать: --change-section-lma .eeprom=1. Где это в студии - не знаю. В моем makefile тут:
eess9, я бы не стал ковырять конфиг линкера. ИМХО оно того не стоит - больно долго все это утрясать. Тем более, что, как показывает практика, не стоит ковырять без нужды то, что генерируется автоматически...
А чем Вам не нравится вариант со структурой? Все просто, логично и совершенно стандартно.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Да, так и сделаю, просто контроллер ATXmega128A3U. У него в 2 килобайтах eeprom хранится 4 массива uint8_t по 100 значений в каждом, 4 массива uint16_t по 100 значений в каждом и еще массив переменной структуры 15 штук по байт этак 15 в каждом. Поэтому почти все 2 килобайта заполнены. И именно поэтому не хотелось все это ворошить, т.к. уж очень много всего. Все массивы могут меняться во время работы (в смысле не константы), поэтому как я не извращался, выпихнуть их во флеш ну нет никакой возможности, т.к. их надо изменять.
Так а особо ворошить не придется. Просто объявления убираем под структуру, а потом автозаменой меняем все обращения по старым именам переменных на "имя_структуры.старое_имя_переменной".
Разница между теорией и практикой на практике гораздо больше, чем в теории.
YS писал(а):а потом автозаменой меняем все обращения по старым именам переменных на "имя_структуры.старое_имя_переменной".
В пятой студии для этого достаточно будет правым кликом выбрать меню переименовать переменную Или горячая клавиша shift+alt+R И все , остальное студия сама сделает...