Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: резервирование места в ОЗУ
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
yung
Здравствуйте! Работаю с Atmega128 и компилятором ICC6.31. Возникла необходимость, чтобы ряд глобальных переменных находился по фиксированным адресам. Сделал это путем, предложенным встроенным application builder-ом

void mapping_init(void)
{
asm(
".area memory(abs)\n"
".org 0x0a00\n"
" _temp1:: .blkb 4\n"

".text\n"
);
}

В АВР-студио эта процедура не видится (стоит ret) вместо тела. А компилятор не видит, что эта область занята и пытается по тем же адресам расположить другие переменные. Можно ли как-то объяснить ему, что место уже занято?
LexaK
А как в ИАРе не получится?
Код
__no_init volatile char a @ 0x8000;
yung
Цитата(LexaK @ Jan 13 2012, 20:09) *
А как в ИАРе не получится?
Код
__no_init volatile char a @ 0x8000;

Не получилось. Пока обошел, разместив переменные в начале ОЗУ. Но вопрос остается открытым. Кстати, заметил интересную особенность. Адреса переменных фактически прижаты к верхней границе ОЗУ (не считая стека). А переменные, инициализируемые одновременно с объявлением (char a=8;) - в начале. Пришлось инициализировать их отдельно.
Палыч
Цитата(yung @ Jan 13 2012, 18:37) *
В АВР-студио эта процедура не видится (стоит ret) вместо тела.
Ваша процедура не содержит ни одного исполняемого оператора. Что Вы ожидали увидить кроме RET?

Цитата(yung @ Jan 13 2012, 18:37) *
А компилятор не видит, что эта область занята и пытается по тем же адресам расположить другие переменные.
Этот механизм не для того, чтобы "двигать" переменные по ОЗУ туда-сюда, как Вы этого желаете, а для доступа к регистрам устройств, спроецированных на память...

Цитата(yung @ Jan 13 2012, 18:37) *
Можно ли как-то объяснить ему, что место уже занято?
Нет. Но, можно сделать другой финт: сказать транслятору, что размер памяти меньше, чем есть на самом деле, а остаток использовать для распределения переменных по фиксированным адресам.
yung
Цитата(Палыч @ Jan 14 2012, 09:58) *
Но, можно сделать другой финт: сказать транслятору, что размер памяти меньше, чем есть на самом деле, а остаток использовать для распределения переменных по фиксированным адресам.

А можно поподробнее? И не будет ли проблем в том, что у меня еще 128кБ внешней памяти стоит?
Палыч
Цитата(yung @ Jan 14 2012, 11:16) *
А можно поподробнее?

1. Menu -> Project -> Options -> Target
2. Device Coinfiguration = Custom
3. Internal SRAM. Если есть внешнее ОЗУ, то задаём ключем -bdata:XXXX.YYYY в Other Options

Если желаем освободить область в:
1) нижних адресах Internal RAM - увеличиваем Data Address
2) верхних адресах Internal RAM - уменьшаем Data Memory
3) нижних адресах External RAM - увеличиваем значение XXXX в ключе -bdata:XXXX.YYYY
4) верхних адресах External RAM - уменьшаем значение YYYY в ключе -bdata:XXXX.YYYY

Цитата(yung @ Jan 14 2012, 11:16) *
И не будет ли проблем в том, что у меня еще 128кБ внешней памяти стоит?
Если посмотреть в DS:
Цитата
Up to 64Kbytes Optional External Memory Space
Вероятно речь идет о внешней памяти, подключенной минуя шины адреса\данных МК?
Artem_Petrik
Цитата(yung @ Jan 13 2012, 16:37) *
Здравствуйте! Работаю с Atmega128 и компилятором ICC6.31. Возникла необходимость, чтобы ряд глобальных переменных находился по фиксированным адресам.

Читая последние ответы можно подумать что нормального способа сделать это нет. Но, к счастью, это не так. Отсутствие возможности разместить перемееную по конкретному адресу звучит для меня настолько дико, что я просто не могу в это поверить.

Никогда не пользовался ICC-шным компилятором, но все же не поленился залезь в хелп у них на сайте, где нашел такое:
Код
#pragma abs_address

In a C file, put the following:

    #pragma abs_address:0x1000
    unsigned LCD_control_register;
    #pragma end_abs_address

    #pragma abs_address:0x2000
    unsigned char dual_port_SRAM[100];
    #pragma end_abs_address

These variables may be declared as extern per the usual C rules in other files. Note that you cannot initialize them in the declarations.

Насколько я понимаю, это именно то, что вам требуется.

P.S. Раздел хелпа "Addressing Absolute Memory Locations". Там еще про то же на ассемблере.
Палыч
Цитата(Artem_Petrik @ Jan 15 2012, 02:00) *
Насколько я понимаю, это именно то, что вам требуется.

Это - решение для ICC v7. У TC - шестая версия: в ней аналог приведенного Вами - ассемблерная вставка, приведенная ТС в первом посте.
Но у ТС теперь другая проблема: в ICC хоть и можно разместить переменную по любому адресу, но делается это через секцию "abs", котрая перекрывается любой другой секцией данных. Поэтому, не исключено, что транслятор разместит по этому адресу некие другие данные...
Artem_Petrik
Цитата(Палыч @ Jan 15 2012, 09:52) *
Это - решение для ICC v7. У TC - шестая версия: в ней аналог приведенного Вами - ассемблерная вставка, приведенная ТС в первом посте.
Но у ТС теперь другая проблема: в ICC хоть и можно разместить переменную по любому адресу, но делается это через секцию "abs", котрая перекрывается любой другой секцией данных. Поэтому, не исключено, что транслятор разместит по этому адресу некие другие данные...

Да, действительно, не обратил внимания на версию. Хелп на сайте уже на 8. Тогда действительно видимо придется договариваться с линкером.

ТС: я бы все же рекомендовал задуматься над сменой компилятора на нормальный. GCС и лучше и бесплатней, а если совести нет - то IAR имхо лучше всех.


yung
Спасибо всем откликнувшимся! Отдельное и огромное - Палычу!
Зарезервировал нижние 128 байт - все работает. При обмене устройства с ПК (в т.ч. для отладки) ввел команды доступа к ОЗУ. Соответственно потребовалось зафиксировать адреса "интересных" переменных для чтения плюс наложить маску по адресам на запись.
А внешнее ОЗУ действительно 128к. Дополнительный адресный бит заведен на отдельный пин в/в, а в старшей половине хранится несколько массивов, которые для обработки перегружаются в нижнюю часть ОЗУ.
Что касается компилятора - привык я к нему sm.gif. Лет 10 уже использую. Особенно нравится аппликэшн билдер. Хотя периодически возникают проблемы. В текущем проекте столкнулся с ситуацией, когда компилятор не смог корректно осилить операцию байтового копирования *(adr1++)=*(adr2++) - писал нули. ICC7 есть, но использовал только когда работал с мега2561. Есть там какие-то нюансы по переносимости, разбираться не стал. IAR когда-то показался слишком заумным для начинающего.
Палыч
Цитата(yung @ Jan 16 2012, 09:50) *
Хотя периодически возникают проблемы. В текущем проекте столкнулся с ситуацией, когда компилятор не смог корректно осилить операцию байтового копирования *(adr1++)=*(adr2++) - писал нули.

Из известных ошибок в ICC версии 6 мне известны две:
1. Неверно вычисляются длинные выражения. Например, такое преобразование из символов в число
Код
X= ((((Buffer[2] - '0') * 10 + (Buffer[3] - '0') ) * 10) + (Buffer[4] - '0') ) * 10) + Buffer[5] - '0';

Так и не смог разобраться, что за код компилятор "наворотил" - кажется, что-то неверно с длиной переменных в начале вычисления выражения... Эта ошибка присутствует как в версии 6, так и в версии 7.
2. Разрушение регистров R0, R1 в прерывании, при обращении к массиву
Если в прерывании есть обращение к элементу массива и нет обращений к функциям, то при входе в процедуру прерывания сохраняются не все регистры, а только те, которые компилятор использует для выполнения кода процедуры прерывания. Для доступа к элементу массива используются R0 и R1, вот, только, компилятор "забывает" их сохранить, а при выходе из прерывания - восстановить. В версии 7 эта ошибка устранена.

Цитата(yung @ Jan 16 2012, 09:50) *
ICC7 есть, но использовал только когда работал с мега2561. Есть там какие-то нюансы по переносимости, разбираться не стал.
Нюансов по переносимости как-то не заметил, но, результирующий размер кода куда бОльший (процентов на 10-15), чем даёт версия 6.
yung
Вот еще проблема с ICC6.31a. Все та же 128-я мега. После увеличения размера кода пошла ругань вида: 'text' area too large (>64K byte) и предложение перенести часть кода в другой файл. При чем здесь 64кБайт? Именно килобайт, а не килослов. Если закомментировать небольшую часть кода, то нормально компилится с результатом 55%. Версия "Professional".
hd44780
Эта бяка другого рода - у этой меги память 128 килобайт, а компилятор этого не понимает.
Лечится какими-то настройками проекта. Какими именно - не знаю, не пользовался, но где-то читал об этом.

Насчёт "килослов". Единица измерения всегда байт, а не слово. То, что АВРы шьют флэш словами, а не байтами - это "их проблемы", не влияющие на общепринятую терминологию.
Современные x86 процы имеют ШД 32 бита (4 байта). Но мы же не начинаем из-за этого измерять объём каких-то данных в двойных словах?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.