Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Инициализация стека STM32
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
igorle
STM32F103 Keil StdPeriph.

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

Насколько я понимаю, размер стека задается в файле startup_stm32f10x_md.s таким образом:
Код
Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp

...

__Vectors       DCD     __initial_sp              ; Top of Stack
                DCD     Reset_Handler             ; Reset Handler
                DCD     NMI_Handler               ; NMI Handler
                DCD     HardFault_Handler         ; Hard Fault Handler
                DCD     MemManage_Handler         ; MPU Fault Handler
При этом в одном проекте SP инициализируется значением 0x200004D0, в другом 0x200008F0

Вопросы:
- Как образуются эти числа? Я ожидал видеть там 0x20000400
- Что находится под стеком?

A. Fig Lee
Смотрите линкер файл. В IAR это .icf файл
igorle
А если Кейл - куда смотреть?
ViKo
Стек растет вниз, в сторону уменьшения адресов. А навстречу ему движется "куча", из которой выделяется память. И все это находится выше переменных.
А посмотреть можно в файле *.map.
aaarrr
Цитата(igorle @ Sep 30 2013, 00:30) *
А если Кейл - куда смотреть?

.scat

Вам нужно найти начало секции STACK. __initial_sp будет равен <начало STACK> + Stack_Size.
_NB
Цитата(igorle @ Sep 29 2013, 22:08) *
Вопросы:
- Как образуются эти числа? Я ожидал видеть там 0x20000400

В 'startup_stm32f10x_md.s' вы задаёте размер стека, а не адрес его начала.

Цитата
- Что находится под стеком?

Для Keil-a посмотрите map-файл
A. Fig Lee
Цитата(_NB @ Sep 30 2013, 06:41) *
В 'startup_stm32f10x_md.s' вы задаёте размер стека, а не адрес его начала.


Для Keil-a посмотрите map-файл

1. Именно что начало.
2. Мап это не тот файл, это результат.
ViKo
Вот такие наблюдения. В проекте в стартапе задано размер стека 0x400, размер кучи 0x200. В map файле вижу:
Код
    Base Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x20000000   0x00000008   Data   RW            4    .data               telt_test.o
    0x20000008   0x00000060   Zero   RW          139    .bss                c_w.l(libspace.o)
    0x20000068   0x00000200   Zero   RW           55    HEAP                startup_stm32f10x_hd.o
    0x20000268   0x00000400   Zero   RW           54    STACK               startup_stm32f10x_hd.o

В отладчике вижу, что стек инициализируется значением 0x20000668.
igorle
MAP файл нашел. Стало понятно, что за цифры я получал и почему они разные. Стек объявляется НАД всеми данными.

Мне это не нравится. Ведь это означает, что если я выйду за пределы стека - то я потру свои переменные. И ловить такую ошибку очень трудно. Я бы хотел разместить стек ПОД всеми данными. Начиная с 0х20000000. Тогда при выходе за стек я получу hard fault.

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

Цитата(aaarrr @ Sep 30 2013, 00:13) *
.scat

Вам нужно найти начало секции STACK. __initial_sp будет равен <начало STACK> + Stack_Size.

Я не нашел такого файла. Есть <target>.sct. Но он тоже автогенерится. Там есть такая секция
Код
  RW_IRAM1 0x20000000 0x00005000  { ; RW data
   .ANY (+RW +ZI)
  }

Возможно, если бы я мог повлиять на этот файл, я мог бы переместить стек туда, куда мне надо.
toweroff
Цитата(igorle @ Sep 30 2013, 22:33) *
Возможно, если бы я мог повлиять на этот файл, я мог бы переместить стек туда, куда мне надо.

конечно возможно)
нужно снять галку - Use Memory Layout from Target Dialog - и правим скаттер руками
обзываем область стека как нужно и в скаттере даем указание где расположить
скорее всего, там обозначен один регион для .ANY (+RW +ZI), так вот нужно просто создать свой регион и обозначить его точку вхождения и размер
LOAD REGION определяет то, как будет располагаться образ, записываемый программатором (ну или бутлоадером)
А вот уже в нем расписываются все секции - где код, где данные, где оставить окно и т.д.
igorle
<Спустя полчаса>
Все, спасибо всем. Дошло. Я могу отменить "Use Memory Layout..." на закладке Linker в свойствах проекта, и задать свой скаттер файл. Уже видно, что это не тривиальная задача - написать скаттер файл, но понятно куда грести.
Еще раз всем спасибо.
toweroff
http://infocenter.arm.com/help/topic/com.a...51a/DUI0151.pdf

в помощь
igorle
2toweroff - Спасибо. Жаль что вы написали предыдущее сообщение одновременно со мною sm.gif Теперь никто не поверит, что я сам сообразил, и написал одновремнно с вами sad.gif

И за линк спасибо. Документу уже 12 лет, а не потерял актуальности. Я сам не нашел такого хорошего руководства по линковщику.
toweroff
Цитата(igorle @ Oct 1 2013, 12:06) *
Жаль что вы написали предыдущее сообщение одновременно со мною sm.gif Теперь никто не поверит, что я сам сообразил, и написал одновремнно с вами sad.gif

а оно кому-нибудь надо? sm.gif
Цитата(igorle @ Oct 1 2013, 12:06) *
И за линк спасибо. Документу уже 12 лет, а не потерял актуальности. Я сам не нашел такого хорошего руководства по линковщику.



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

редактор
Раз уж речь пошла об инициализации, спрошу здесь (хоть и не совсем в тему, да простят меня автор топика и Модераторы).
Можно ли в KEIL узнать остаток кучи (HEAP) штатными средствами?
Или только через контроль указателя, который вернулся при запросе (через new) и несложную математику?
igorle
А что такое "остаток"? Память ведь может быть фрагментирована. Сумма всех кусочков?

Единственный путь, известный мне, это в нужной точке устроить крэш тест: аллоцировать память, пока не вернет ошибку. Но и это мало информации дает, так как фрагментация памяти и размер запрашиваемых блоков играют важную роль.
toweroff
Цитата(igorle @ Oct 2 2013, 18:35) *
А что такое "остаток"? Память ведь может быть фрагментирована. Сумма всех кусочков?

Единственный путь, известный мне, это в нужной точке устроить крэш тест: аллоцировать память, пока не вернет ошибку. Но и это мало информации дает, так как фрагментация памяти и размер запрашиваемых блоков играют важную роль.
да, я тоже видел подобные примеры в тырнете. While для malloc с инкрементом размера и освобождением, пока не вернет NULL

тут ведь какая штука... черт ее знает, как там менеджер кучи работает. Может он умеет "собирать крупу" sm.gif


A. Fig Lee
Цитата(редактор @ Oct 2 2013, 04:02) *
Раз уж речь пошла об инициализации, спрошу здесь (хоть и не совсем в тему, да простят меня автор топика и Модераторы).
Можно ли в KEIL узнать остаток кучи (HEAP) штатными средствами?
Или только через контроль указателя, который вернулся при запросе (через new) и несложную математику?

Keil это компилятор. Вы хотите узнать сколько осталось после компиляции?
мап файл.
Если в процессе работы программы, то Keil тут никаким боком.
Зависит от операционки, если она есть.
редактор
Спасибо всем за ответы.
Цитата
А что такое "остаток"? Память ведь может быть фрагментирована. Сумма всех кусочков?

Ну примерно так. Если подробнее, то до вызова main() происходит инициализация статических переменных и классов. При инициализации классов часть памяти "захватыватся" через new. Вот и хотелось бы узнать хоть приблизительный остаток кучи (к этому моменту она еще не будет дефрагментирована, надеюсь) или размер максимального блока, который может быть выделен.
Использовать статическое выделение памяти можно, но это уже другая тема (мое наследство), поэтому не обсуждаю.

Цитата
Keil это компилятор. Вы хотите узнать сколько осталось после компиляции? мап файл.

Тогда уж после линковки (но это я к словам докапываюсь, извините). Это я в курсе.
Но тем неменее KEIL предоставляет несколько функций для работы с кучей, не относящихся к стандартным. Например __heapstats(); ее недостатком является то, что информацию выдает через printf в текстовом виде, да и информация по каждому блоку отдельно - не совсем то, что надо.
Думал, может кто с другими функциями контроля знаком.
igorle
Вызовите в начале функции main маллок одного байта, поставьте там брекпоинт. Посмотрите, что вернул маллок и насколько это далеко от границы кучи. Освободите этот байт.

Хочется автоматизации - аллоцируйте и осбобождайте блок памяти в цикле, добавляя по одному байту. Когда будет достигнут предел - напечатайте, или зайдите в брекпоинт. Я так понимаю, речь идет не о рабочем коде, а об отладочном - чтобы оценить достаточность кучи?
редактор
Спасибо за совет. В данный момент речь идет именно об отладочном коде.
Но использование в реалтайме тоже могло бы пригодиться.
Есть мысль, что в начале main достаточно запросить один байт и по указателю рассчитать остаток.
HEAP_MEM + HEAP_SIZE - PTR
точность составит наверное 8-16 байт (округление запрошенной памяти до 8 байт + параметры под атрибуты блока) но для первоначальной оценки вполне достаточно.
Еще раз всем спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.