Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: задание размера стеков
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > Keil
poq12
Четкого ответа на данный вопрос я для себя найти не смог, поэтому решил задать его здесь. Собственно вопрос:
(использую LPC2148, среда Uvision3, компилятор RealView)
Я продумал алгоритм как должна работать программа, чтобы железо выполняло желаемые действия, написал её, скомпилировал, зашил в процессор - все работет, претензий нет. Впроцессе написания нужно задать размер стэков для разных режимов работы процессора в файле "startup.s", в частности например, режимов "supervisor mode" - 8bytes, "interrupt mode"- 80 bytes, "user/system mode" - 400bytes. Количество отводимых байт я брал "от балды" исходя из того сколько указано в идущих примерах.
Теперь сам вопрос - как узнать сколько байт для стэка нужно выделять данным режимам, с чего например брать 400, а не 300 ... и так и так будет работать ... Как узнать сколько байт под стэк нужно выделить, чтобы и мало не было и слишком много не дать ... smile3046.gif
zltigo
Цитата(poq12 @ Sep 2 2009, 23:10) *
Четкого ответа на данный вопрос я для себя найти не смог....

Ну никто, кроме Вас на него и не ответит. Смотрите сами какие режимы используете, какие фунции вызываете.... В map/list файлах обычно бывает информация об использовании стека функциями. Прикидывайте, думайте.
@Ark
Можно попытаться найти "наихудший случай" (для стека) - то есть такое сочетание вызовов и возможных прерываний, при котором стек будет использован максимально. Иногда это получается.
Есть еще "экспериментальный" способ. Задаете стек с большим запасом. В начале работы программы заполняете всю область стека известными значениями (нулями, например). Даете поработать программе какое-то время на различных режимах, и затем смотрите - какая часть стека оказалась "затертой" (была использована).
poq12
Спасибо за ответы smile.gif
ViKo
Как расположить стек по заданному адресу?
Когда я задаю в свойствах проекта, что будет внешняя ОЗУ по адресам 0x64000000...0x40000, __initial_sp становится равным 0x64000400.
Ну а дальше в определенный момент вываливается HardFault (это потом буду исследовать).
Вручную в startup задать __initial_sp 0x20000400?
zltigo
Цитата(ViKo @ May 13 2010, 17:08) *
Когда я задаю в свойствах проекта...

Давить все эти "свойства проекта" сразу нафиг и написать скрипт линкера самостоятельно, благо сие обычно документировано неплохо, да и сложности не представляет особой. Болванки образчики тоже есть.
ViKo
Цитата(zltigo @ May 13 2010, 17:15) *
Болванки образчики тоже есть.

Так дайте мне какую-нибудь болванку smile.gif
Если не трудно.
upd. В тех scatter-файлах, что я вижу в хэлпе, не нахожу упоминания стека.

Что непонятно - в файле startup_stm32f10x_hd.s вижу стек по адресу 0x20000400.
Как запускаю симулятор - загружается 0x64000400.
zltigo
Цитата(ViKo @ May 13 2010, 17:43) *
Так дайте мне какую-нибудь болванку smile.gif

Легко. У меня сейчас пока такая болванка IAR V5 для Сortex-M3, но Luminary, что совершенно не принципиально - только старшую часть таблицы векторов в соответствие с таблицей другого производителя подправить и все. Стек просто размещается в noinit секции, но естествено можно создать линкером и свою в желаемом месте.
Цитата
Что непонятно - в файле startup_stm32f10x_hd.s вижу стек по адресу 0x20000400.
Как запускаю симулятор - загружается 0x64000400.

А с чего Вы решили, что у Вас именно он используется? Его конкретно в проект запихнули? В том, что у Вас явно он уже в библиотеке скомпилированная и указатель на стек линкером из *.icf берется. Вообще, если в каком-то startup есть явное указателя на стек, то это явный дибилизм - ликер об этом не знает и спокойно когда-нибудь туда память распределит sad.gif. Конечно,можно какую-то область памяти у линкера забрать, но тогда придется согласовывать числа в startup и линкере. Зачем?
ViKo
Я конкретно не указывал стек, иначе зачем бы я вопрос задавал.
Как только указал в настройках, что есть внешняя память, и отметил птички default и noinit, так он сам туда переназначается. В симуляторе вижу R13(SP)=0x64000400.
Убрал птичку default с адресов 0x64000000... - стек стал таким, как надо. Похоже, с этой бедой я "справился" smile.gif
За файлик - спасибо!

А что ж тогда эта птичка default делает?
zltigo
Цитата(ViKo @ May 13 2010, 20:30) *
А что ж тогда эта птичка default делает?

Верите, но отродясь во всякие визардики с галочками не заходил, посему не знаю и знать не хочу.
ViKo
Цитата(zltigo @ May 13 2010, 20:43) *
Верите, но отродясь во всякие визардики с галочками не заходил, посему не знаю и знать не хочу.

То - не визард, а опции для проекта, закладка Target. В другие закладки Вы же заходили, процессор выбирали, отладчик выбирали, оптимизацию...?
А, Вы же в IAR работаете...
zltigo
Цитата(ViKo @ May 13 2010, 21:11) *
В другие закладки Вы же заходили

Зачем. если есть отработанный и отполированный и, что самое главное ДОКУМЕНТИРОВАННЫЙ интерфейс командной строки? В IDE захожу дабы собрать покрутить какие-либо образчики чужих проектов. И все. Но даже в IDE есть возможность подсовывать вой скрипт и
работать не с мутными галочками а с параметрами командной строки.



Цитата(ViKo @ May 13 2010, 21:11) *
То - не визард

Визард и есть - вместо нормального управления несколько готовых рецептов - пипл хавает sad.gif
ViKo
Цитата(zltigo @ May 13 2010, 21:20) *
Зачем. если есть отработанный и отполированный и, что самое главное ДОКУМЕНТИРОВАННЫЙ интерфейс командной строки? В IDE захожу дабы собрать покрутить какие-либо образчики чужих проектов. И все. Но даже в IDE есть возможность подсовывать вой скрипт и
работать не с мутными галочками а с параметрами командной строки.

Это вопрос личных предпочтений. А на этапе освоения визард - самый легкий путь. Но не всегда кратчайший.
Я вот связался с библиотекой от ST, теперь ноги разъезжаются, не знаю где глюки искать, или какую еще функцию не вызвал. Но "на переправе коней не меняют". Заработает - начну с нуля, все свое писать.
ViKo
По поводу размера стека поделюсь информацией.
Был у меня стек 0x0400, как, собственно, и стоял в startup. Думал я, зачем столько? Потом смотрю в симуляторе - осталось 0x040 примерно. Оказывается, когда инициализировал контроллер ЖКИ, висящий на внешней шине, процессор перенес массив констант для инициализации из флэш-памяти в стек, а уж потом оттуда по-быстрому забросил в контроллер ЖКИ. Кто бы мог подумать? smile.gif
aaarrr
Цитата(ViKo @ May 16 2010, 00:10) *
Кто бы мог подумать? smile.gif

Писатель должен был подумать, вообще-то. В стек компилятор просто так ничего не упихивает, если его не попросить.
Genadi Zawidowski
Цитата
процессор перенес массив констант для инициализации из флэш-памяти в стек


Код
void f(...)
{
static const unsigned char a [] = {0x01, 0x02, 0x03 };
}


Если кто-то забыл static написать, так и будет.
ViKo
Неправильно сказал - не через стек переписывает, а через память, отведенную под стек. Переносит указатель на 0x040, и в свободной области создает буфер для этих констант. Потом обратно стек восстанавливает.
А за static - спасибо, попробую.
upd. Попробовал - помогло. И размер кода уменьшился (естественно smile.gif)
ViKo
Можно вопрос, не по теме, но непосредственно вытекающий из предыдущего.
Почему симулятор Keil останавливается на командах, которыми я инициализирую контроллер ЖКИ на внешней шине, и ходит только по шагам?
aaarrr
А Вы окошечки сообщений посмотрите: он, наверное, ругается на запись/чтение левых адресов.
ViKo
Цитата(aaarrr @ May 18 2010, 18:31) *
А Вы окошечки сообщений посмотрите: он, наверное, ругается на запись/чтение левых адресов.

Точно, пишет! В окне command:
*** error 65: access violation at 0x6C000070 : no 'read' permission
а потом и на запись аналогично ругается.

Вообще, складывается впечатление, что в окне Options/Target Keil 4.10 имеется глюк. Привожу все варианты установок и результат их действия после запуска программы в симуляторе. Адрес 0x6C000070 - первый из используемых (регистр контроллера ЖКИ), адрес 0x6C020000 - память контроллера ЖКИ.
Код
default--Start-------Size-------NoInit--access_violation--R13(SP)
---------0x6c000000--0x40000------------0x6C000070--------0x2000041C
---------0x6c000000--0x40000-----v------0x6C000070--------0x2000041C
-v-------0x6c000000--0x40000------------0x6C020000--------0x6C000414
-v-------0x6c000000--0x40000-----v------0x6C020000--------0x6C000414

Т.е., отмечаю default - там создается стек, NoInit - вообще никак не влияет.
А size там в каких единицах задавать, в байтах?
Придется изучать синтаксис scatter файла...
Пока отформатировал данное послание, упарился...
ViKo
А на такой вопрос подскажите, в чем дело (может, и предыдущий разрешится):
Отмечаю v default регион start 0x6c000000 size 0x40000, имею в scatter файле:
RW_RAM3 0x6C000000 UNINIT 0x00040000 { ; RW data
.ANY (+RW +ZI)
Стек, как и раньше, закидывается в 0x6c000414.
Запускаю симулятор, останавливается с ошибкой
*** error 65: access violation at 0x6C020000 : no 'read' permission
Это как? Разрешена же область! Или со стеком связано? Ведь перед этим обращался к адресам 0x6c000000... без ошибок.
А еще есть эта... куча...!?
aaarrr
Цитата(ViKo @ May 19 2010, 14:28) *
Отмечаю v default регион start 0x6c000000 size 0x40000, имею в scatter файле:
...
Запускаю симулятор, останавливается с ошибкой
*** error 65: access violation at 0x6C020000 : no 'read' permission
Это как? Разрешена же область!

Scatter-файл относится к линкеру, а ошибка к симулятору. Если хотите, чтобы последний не ругался на записи по левым адресам, создайте ini-файл со строкой:
Код
map 0x6c000000, 0x6c0fffff READ WRITE

И подцепите его в качестве Initialization File для симулятора.
ViKo
Цитата(aaarrr @ May 19 2010, 14:09) *
Scatter-файл относится к линкеру, а ошибка к симулятору.

Я думаю, симулятор знает, что сделал линкер. Иначе он бы останавливался при первом же обращении в эту область, по адресу 0x6c000070.
aaarrr
Цитата(ViKo @ May 19 2010, 15:21) *
Я думаю, симулятор знает, что сделал линкер.

А вот линкеру как раз знать об этой области ничего не надо - вы же не хотите, чтобы по адресам регистров LCD он распихал данные программы.
Просто объясните симулятору, что такая область есть. Как это делается я написал выше, только диапазон адресов расширьте.
ViKo
Цитата(aaarrr @ May 19 2010, 14:35) *
А вот линкеру как раз знать об этой области ничего не надо - вы же не хотите, чтобы по адресам регистров LCD он распихал данные программы.
Просто объясните симулятору, что такая область есть. Как это делается я написал выше, только диапазон адресов расширьте.

Спасибо, получилось! А я еще недоумевал, почему в симуляторе останавливается, а в железе работает.
А внешние ОЗУ и ПЗУ мне линкеру указывать?
aaarrr
Цитата(ViKo @ May 19 2010, 15:49) *
А внешние ОЗУ и ПЗУ мне линкеру указывать?

Если в них надо разместить код/данные - то указывать. Если они просто существуют, но не используются, то и указывать не за чем.
ViKo
В-общем, эта птичка default именно для этого и создана - подключать или отключать заданный регион памяти в проект. Если ее убрать в опциях Target, в scatter файле заданной цифрами области не будет.
ViKo
Возвращаюсь к теме.
Хочу для STM32F303 в Keil задать стек в конце CCM-RAM. Но что-то не выходит. Как это сделать, и можно ли? В startup.s или в *.sct?
Хочу понять строки в startup.s
CODE

Stack_Size EQU 0x00000400

AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
...
Heap_Size EQU 0x00000000

AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
...
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size

__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
...
;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
IF :DEF:__MICROLIB

EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit

ELSE

IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap

__user_initial_stackheap

LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR

ALIGN

ENDIF
ViKo
Ого, блин! В AN4296 "Overview and tips for using STM32F303/313xx CCM RAM..." Rev.2 в разделе KEIL ошибочно заменили Figure 11 на такую же из IAR (Figure 2). Без этой картинки нихрена не понять.
К счастью, нашел в корзине удаленный файл Rev.1.
ViKo
Добавляю в *.sct
ARM_LIB_STACK 0x10002000 EMPTY -0x0400 { }
не помогает.
Вау - работает, вижу в отладчике SP = 0x10002000
Но когда всю обычную RAM (не CCMRAM) пытаюсь забрать под массив, не складывается.
Т.е. теперь вопрос - как разместить остальные переменные в CCMRAM.
В неё же у меня и код перегружается, и из нее выполняется.
В-общем, что-то со стеком, сначала в основной памяти размещается, а потом в CCM. Приступаю штудировать доку по линкеру.

Кстати, в Keil для IRAM1 указан неправильный размер, надо A000 (40k) вместо C000 (48k).
Из-за этого компилируется без ошибок, а после запуска вываливается в HardFault.
А все потому, что стек размещается сразу после всех переменных (+ куча, если есть), а не в конце RAM. И когда память не была забита, хватало места и для стека.
-JonnS-
Цитата(ViKo @ Apr 3 2014, 10:36) *
как разместить остальные переменные в CCMRAM.

Я делал так:
в Scatter-файл обявляю:
Код
LR_IRAM2 0x10000000 0x00010000  {
  RW_IRAM2 0x10000000 0x00010000  {
    *(CCM_RW)
   .ANY (+RW)
  }
}

в "main.c"
Код
#pragma arm section rwdata = "CCM_RW"
uint8_t h[] = {1, 2, 3};
#pragma arm section rwdata

#pragma arm section zidata = "CCM_RW"
SAMPLE M_Buf[COUNT];
#pragma arm section zidata

Надеюсь поможет.
ViKo
Цитата(-JonnS- @ Apr 4 2014, 13:58) *
Я делал так:
...
Надеюсь поможет.

Спасибо. Я уже все сделал, поизвращался со scatter файлом по-всякому.
Разместил массив в основной памяти, забрал всю под завязку, все 40 KB.
В CCMRAM разместил стек, код и остальные переменные.
Все работает замечательно. rolleyes.gif
CODE

LR_IROM1 0x08000000 0x040000 { ; load region size_region
ER_IROM1 0x08000000 0x040000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
ER 0x10000800 0x001800 { ; load address = execution address
.ANY (ccmram)
}
ARM_LIB_STACK 0x10000800 EMPTY -0x000200 { ; stack
;
}
ARM_LIB_HEAP +0 EMPTY 0 { ; heap
;
}
RW_IRAM1 0x20000000 ANY_SIZE 0x00A000 0x00A000 { ; RW data, WaveBuff
; .ANY (+RW +ZI)
.ANY (wave)
}
RW_IRAM2 0x10000000 0x002000 { ; CCMRAM
.ANY (+RW +ZI)
}
}


P.S. размер CCM памяти у вас великоват, 64K. Разве там столько ее?
P.P.S. основной затык был в неправильном размере памяти в Кейле (писал выше), и что в процессе создания стека нужно иметь еще столько же пустой. Последнее мне не совсем понятно, не докопался.
-JonnS-
CCM-Ram у F4xx вроди как 64k. Пример под F4 discovery писался, sorry не уточнил.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.