Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Почему в small-модели стеки находятся снизу?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Xenia
Почему в small-модели стеки находятся снизу и как это исправить?

Работая с ATtiny2313 я уже привыкла к тому, что стеки (CSTACK и RSTACK) находятся сверху (в старших адресах). Это было очень удобно тем, что в программе можно было явно установить указатель RSTACK'а на самый верх, тем самым, задействуя всю неиспользованную память под стеки. Вручную же рассчитывать размеры стеков крайне неудобно, т.к. CSTACK запрашивают в байтах, а RSTACK в словах. А я не арифмометр, чтобы подбирать эти значения так, чтобы они вписались во весь объем памяти. Тем более что такую операцию мне пришлось бы выполнять каждый раз, когда бы я заводила или удаляла какую-нибудь переменную или изменяла размеры массива. А так, устанавливаешь указатель на вершину памяти и никакой тебе головной боли.
Однако перейдя со временем на МК с большим объемом ОЗУ, пришлось перейти и на модель памяти small. И тут меня ждало неприятное известие о том, что теперь стеки находятся внизу, за ними данные, а пустое пространство сверху. Теперь его уже никак нельзя использовать, кроме как вручную каждый раз изменять размеры стеков в проекте.
В таком расположении стеков я ничуть не виновата - IAR так делает сам. Вот посмотрите на контрольный тест для ATmega8. Этот МК выбран только потому, что допускает обе модели памяти: как tiny, так small. Пишу простейшую программу, содержащую массив данных Buffer, и компилирую ОДИН И ТОТ ЖЕ ПРОЕКТ на tiny и small моделях, переключая в проекте ТОЛЬКО тип модели и не трогая ничего остального.

Код
unsigned char Buffer[70];

C_task main( void )
{
  Buffer[0] = 0;
}

В модели tiny получаю:

Код
SEGMENT              SPACE    START ADDRESS   END ADDRESS     SIZE  TYPE  ALIGN
=======              =====    =============   ===========     ====  ====  =====
TINY_I               DATA               00000060                     dse    0
TINY_Z               DATA          00000060 - 000000A5          46   rel    0
CSTACK               DATA          000000A6 - 000000B9          14   dse    0
RSTACK               DATA          000000BA - 000000C9          10   dse    0

А в модели small вот это:

Код
SEGMENT              SPACE    START ADDRESS   END ADDRESS     SIZE  TYPE  ALIGN
=======              =====    =============   ===========     ====  ====  =====
CSTACK               DATA          00000060 - 00000073          14   dse    0
RSTACK               DATA          00000074 - 00000083          10   dse    0
NEAR_I               DATA               00000084                     dse    0
NEAR_Z               DATA          00000084 - 000000C9          46   rel    0

Абсолютно та же самая ситуация со small-моделью во всех остальных моделях МК (проверяла еще и на AT90USB647).

Мой вопрос: Какими соображениями обусловлено такое распределение памяти в small-модели? Можно ли как-то изменить такое распределение памяти и заставить компилятор размещать данные ниже стеков?
SSerge
Разница в .xcl файлах.
Линкер размещает сегменты в памяти в том порядке, в каком они перечислены в директивах -Z(DATA).
IgorKossak
Xenia, Вы очевидно полагаетесь на конфигурирование Вашего проекта через диалог (General Options->Target->System configuration->Configure system using dialog).
Если хотите держать всё под контролем, конфигурируйте систему через .xcl файл.
Нужный файл нужно скопировать в свой проект из папки /avr/config установленного продукта и указать на него в настройках Linker->Config->Linker command file и править его размещая сегменты как душе угодно.
Xenia
Цитата(SSerge @ Jun 13 2009, 23:21) *
Разница в .xcl файлах.
Линкер размещает сегменты в памяти в том порядке, в каком они перечислены в директивах -Z(DATA).


Это не так!
Для ATmega8 по умолчанию имеются два файла для конфигурации линкера: lnkm8t.xcl (для tiny-модели) и lnkm8s.xcl (для small-модели). Смотрим конфигурацию для small-модели (файл lnkm8s.xcl):

/* Internal data memory */
-Z(DATA)TINY_I,TINY_Z,TINY_N=60-FF
-Z(DATA)NEAR_I,NEAR_Z=60-45F
-Z(DATA)RSTACK+_..X_RSTACK_SIZE=60-45F
-Z(DATA)CSTACK+_..X_CSTACK_SIZE=60-45F
-Z(DATA)HEAP+_..X_HEAP_SIZE=60-45F
-Z(DATA)IOSTREAM_N#60-45F
-Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=60-45F

Как видим, стеки перечислены ПОСЛЕ данных, но, тем не менее, располагаются они в обратном порядке (RSTACK+CSTACK ниже чем NEAR_I+NEAR_Z). Примерно таже последовательность и в файле конфигурации tiny-модели. Если отбросить все то, что к делу не относится (хипы и иостримы), но порядок перечисления сегментов -Z(DATA) для обоих моделей использован одинаковый - память раньше стеков, но результат компиляции получается разный.
Ваше утверждение уже потому не может быть правдой, что в конфигурациях линкера строка RSTACK стоит раньше чем CSTACK, когда как каждому известно, что CSTACK всегда ниже RSTACK'а, т.к. первый растет вверх, а второй вниз.
KRS
Цитата(Xenia @ Jun 14 2009, 00:12) *
RSTACK стоит раньше чем CSTACK, когда как каждому известно, что CSTACK всегда ниже RSTACK'а, т.к. первый растет вверх, а второй вниз.

Это с каких пор CSTACK вверх растет???
Вы листинг смотрели? Там видно сразу куда что растет.
Xenia
Цитата(KRS @ Jun 14 2009, 01:12) *
Это с каких пор CSTACK вверх растет???
Вы листинг смотрели? Там видно сразу куда что растет.

В tiny-модели вроде бы CSTACK кверху рос. Впрочем, я не твердо в том уверена, поскольку старалась локальные переменные в функциях размещать в мусорных регистрах. Но в какую бы сторону ни рос стек, мой вопрос остается в силе. Я привела явные доказательства того, что в small-модели стеки организуются ниже данных. Об этом однозначно свидетельствует выдержка из map-файла, которую я привела в первом сообщении. Пока мой вопрос о причинах этого явления остается без ответа.
KRS
а вы свой XCL файл писали?
Что то у меня всегда сегменты шли в нужном мне порядке...
попробуйте их тогда в одной строчке перечислить! тогда точно в нужном порядке пойдут!
SSerge
Проверил на версии 4.12.
Ещё интереснее, при установленой галке General Options->Target->Configure system using dialog(not in .XCL file) директивы размещения сегментов берутся из \avr\src\template\cfg1soim.xcl или \avr\src\template\cfg1toim.xcl.

А при снятой - из \avr\config\lnkm8s.xcl или \avr\config\lnkm8t.xcl.
Это видно в "шапке" в начале map-файла.

При снятии/установке галки положение сегментов меняется, но именно в соответствии с порядком следования -Z директив в этих файлах.
IgorKossak
Цитата(Xenia @ Jun 14 2009, 00:57) *
Пока мой вопрос о причинах этого явления остается без ответа.

Постараюсь ещё раз.
У Вас было два вопроса: о причинах и соображениях такого распределения и как сделать так как надо.
На первый вопрос Вам ответили, что расположение сегментов описано в xcl файлах. Из чего исходили IARовцы, располагая таким образом сегменты - одному Богу известно. Абсолютно однозначных причин на это нет.
Что касается второго вопроса, то в третьем посте я Вам уже говорил, что нужно сделать. Добавлю только, что если Вы хотите прижать стеки к потолку ОЗУ, то вместо символа "=" надо ставить "#"
Код
-Z(DATA)RSTACK+_..X_RSTACK_SIZE#60-45F
-Z(DATA)CSTACK+_..X_CSTACK_SIZE#60-45F
Xenia
Цитата(SSerge @ Jun 14 2009, 02:19) *
Ещё интереснее, при установленой галке General Options->Target->Configure system using dialog(not in .XCL file) директивы размещения сегментов берутся из \avr\src\template\cfg1soim.xcl или \avr\src\template\cfg1toim.xcl.
А при снятой - из \avr\config\lnkm8s.xcl или \avr\config\lnkm8t.xcl.
Это видно в "шапке" в начале map-файла.
При снятии/установке галки положение сегментов меняется, но именно в соответствии с порядком следования -Z директив в этих файлах.


Огромное спасибо! Теперь мне стала абсолютно ясна причина, по которой у меня расстановка сегментов не соответствовала файлу конфигурации lnkm8s.xcl - компилятор брал его из другого файла cfg1soim.xcl, поскольку та галка у меня в проекте стояла.
Стало быть разница в укладке сегментов следует из содержимого файлов конфигурации cfg1soim.xcl и cfg1toim.xcl.

В модели tiny стеки выше tiny-данных:

-Z(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_TBASE:+_..X_SRAM_TSIZE
-Z(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_SRAM_TBASE:+_..X_SRAM_TSIZE
-Z(DATA)HEAP+_..X_HEAP_SIZE=_..X_SRAM_TBASE:+_..X_SRAM_TSIZE
-Z(DATA)IOSTREAM_N#_..X_SRAM_TBASE:+_..X_SRAM_TSIZE
-Z(DATA)TINY_HEAP+_..X_TINY_HEAP_SIZE=_..X_SRAM_TBASE:+_..X_SRAM_TSIZE
-Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_RSTACK_BASE-_..X_RSTACK_END
-Z(DATA)NEAR_I,NEAR_Z=_..X_SRAM_BASE-_..X_SRAM_END
-Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END
-Z(DATA)NEAR_N=_..X_SRAM_BASE-_..X_SRAM_END

А в модели small стеки ниже near-данных:

-Z(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_TBASE:+_..X_SRAM_TSIZE
-Z(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_CSTACK_BASE-_..X_CSTACK_END
-Z(DATA)HEAP+_..X_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END
-Z(DATA)IOSTREAM_N#_..X_SRAM_BASE-_..X_SRAM_END
-Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END
-Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_RSTACK_BASE-_..X_RSTACK_END
-Z(DATA)NEAR_I,NEAR_Z,NEAR_N=_..X_SRAM_BASE-_..X_SRAM_END

Еще раз спасибо за исчерпывающее разъяснение!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.