|
|
  |
Освоение ARM контроллеров |
|
|
|
Apr 13 2016, 06:10
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zltigo @ Apr 12 2016, 22:13)  Вообще в идеале heap должен занимать ВООБЩЕ ВСЮ свободную память. Посему любые константные дефиниции его размера в корне порочны. Следует слегка постараться и отдавать хипу всю память от конца статически распределенной компилятором до конца памяти контроллера. ЗАЧЕМ??? ...если куча не нужна и не используется нигде в проекте. Во всех моих проектах размер кучи задан ==0 в конфигурационном файле компоновщика. У меня везде так (для IAR): Код define block CSTACK with alignment = 8, size = 0x000 {}; define block HEAP with alignment = 8, size = 0x000 {}; А далее: Код do not initialize {section .bssStk}; do not initialize {section .bssStkMain}; ... place in RAM_regionA {section .BITBAND_RAM, section .dma, section .ethernet}; place in RAM_regionA {rw, first block CSTACK, section .bssMemNoFill, block HEAP}; Стеки задач, основной стек (который указан в reset-векторе) и стек исключений определены подобно: Код #pragma data_alignment = 8 __no_init static OS_STK taskADEStk[64 + STK_SIZE_ISR_NFP] @ ".bssStk"; Иногда я объединяю все стеки (задач, основной стек и стек исключений) в единый сплошной блок через define block. Имхо: определять размеры стеков в си-шных файлах гораздо удобнее, чем в едином конфигурационном файле компоновщика. PS: Контролировать размер стеков конечно нужно. И выделять под них память, а не надеяться что "что-то не налезет на что-то".
|
|
|
|
|
Apr 13 2016, 06:27
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (jcxz @ Apr 13 2016, 09:10)  ЗАЧЕМ??? ...если куча не нужна и не используется нигде в проекте. Ну вообще-то, совершенно очевидно, речь идет о случае, когда куча используется. QUOTE (jcxz @ Apr 13 2016, 09:10)  Имхо: определять размеры стеков в си-шных файлах гораздо удобнее, чем в едином конфигурационном файле компоновщика. Чем? Есть одно место, где описаны все размеры блоков памяти конкретного проекта. Заходишь и смотришь, а не надо ползать искать. Когда пишутся, например, всякие демки на 999 вариантов, тогда в них приходится выносить и размазывать настройки по файлам и ключам. Но для конкретного проекта зачем?
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 13 2016, 07:50
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (ViKo @ Apr 13 2016, 10:25)  Как можно контролировать стек (не задач в RTOS), который растет себе и растет, пока не налезет на кучу или переменные?? Также, как и "задач в RTOS". Какие проблемы? Те стеки тоже "растут себе и растут"... С контролем НЕ в реальном массштабе времени проблем нет. Но вот именно отсутствие контроля в реальном времени как раз и не позволяет на ходу разруливать ситуации со стеком и следовательно по любому под стек нужно выделять гарантированно достаточное место. Потом уже постфактум по результатам контроля, если надо, думать уменьшить его или нет.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 13 2016, 08:43
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zltigo @ Apr 13 2016, 12:27)  Чем? Есть одно место, где описаны все размеры блоков памяти конкретного проекта. Заходишь и смотришь, а не надо ползать искать. Когда пишутся, например, всякие демки на 999 вариантов, тогда в них приходится выносить и размазывать настройки по файлам и ключам. Но для конкретного проекта зачем? Есть задача, у неё свой стек. Все переменные, дефайны этой задачи - в её файлах. Проект состоит из множества таких задач. Естественно что данные, нужные локально только данной задаче, должны быть локальны (описаны именно в её файлах, а не вкаком-то едином файле). А стек - это локальная сущность конкретной задачи. И размер его скорее зависит от данной задачи, а не от проекта в целом. Или Вы и локальные переменные каждой задачи тоже в едином файле определяете?
|
|
|
|
|
Apr 13 2016, 09:01
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (jcxz @ Apr 13 2016, 11:43)  Есть задача, у неё свой стек. Не передергивайте! Речь идет о статически распределяемой памяти. Но, если-бы я с какого-то бодуна выделял стеки задачам статически, то, да и эти БЛОКИ памяти я бы ТОЖЕ описал под линкер, что-бы видеть общую картину в одном месте и сразу при проектировании, а не тогда, кода линкер выругается при линковке что памяти совсем нет. После чего придется ползать по куче файлов и думать где жертвовать. QUOTE А стек - это локальная сущность конкретной задачи. Содержимое стека - несомненно. Но сам стек, как блок памяти, это уже элемент ВЕРХНЕГО, надзадачного уровня. Вот и его выделением и размещением занимается НЕ задача. QUOTE Или Вы и локальные переменные каждой задачи тоже в едином файле определяете?  К чему эта дурацкая фраза и усмешка?
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 13 2016, 09:05
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zltigo @ Apr 13 2016, 13:50)  Также, как и "задач в RTOS". Какие проблемы? Те стеки тоже "растут себе и растут"... С контролем НЕ в реальном массштабе времени проблем нет. Но вот именно отсутствие контроля в реальном времени как раз и не позволяет на ходу разруливать ситуации со стеком и следовательно по любому под стек нужно выделять гарантированно достаточное место. Потом уже постфактум по результатам контроля, если надо, думать уменьшить его или нет. В принципе - можно и в реальном. И даже под многозадачную ОС. С MMU конечно вообще проблем нет такое сделать. Но даже с MPU это возможно. Я уже не раз задумывался чтобы внести такую функциональность в свои проекты, всё руки не доходят. Как: Вынести все стеки задач в единый сплошной сегмент памяти. Закрыть полностью доступ к этому сегменту через MPU. В ISR PendSV при каждом переключении пользовательского контекста, программировать перекрывающую запись таблицы MPU (более приоритетную чем та запись, которая закрывает доступ ко всему сегменту стека) на новый стек (находящийся внутри общего сегмента стека). Конечно будут потери памяти на выравнивании, необходимом для MPU. Но сделать вроде можно. Да - в начале и в конце сегмента стека должны быть небольшие интервалы неиспользуемой памяти. Конечно, если функция внутри задачи написана так, что выделяет размер массива выходящий за границу сегмента стека, то тогда такая защита может не спасти. Но чаще всего доступ к стеку идёт более-менее последовательно, небольшими шагами. Цитата(zltigo @ Apr 13 2016, 15:01)  Если-бы я с какого-то бодуна выделял стеки задачам статически, то, да и эти БЛОКИ памяти я бы ТОЖЕ описал для линкера. А с какого бодуна Вы выделяете стеки задачам динамически? И зачем такое делать? Задачи создавать/убивать? Это лишнее.
|
|
|
|
|
Apr 13 2016, 09:19
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zltigo @ Apr 13 2016, 15:01)  Вот и его выделением и размещением занимается НЕ задача. Размещением стека, как и любой другой статической переменной у меня занимается компоновщик. Не вижу ни малейшего смысла выделять стек динамически. Какая разница кто размещает? Есть разница где эта переменая описана. А описана она должна быть там же, где и прочие локальные переменные задачи. Цитата(zltigo @ Apr 13 2016, 15:08)  Без комментариев, ибо рожденный ползать понять "лишнего" не может  Думаю, что во всех случаях, когда нужно зачем-то создавать/убивать задачи в embedded среде с заранее известным выполняемым функционалом (речь не идёт о системах, в которых заранее не известен список работающих задач, когда задачи запускаются пользователем), всегда можно составить максимальный список задач, которые могут работать одновременно, выделить под них стеки статически и все их запустить. И не убивать их когда работа закончена и создавать заново, а просто приостанавливать выполнение когда необходимо (на мэйлбоксе например), до появления новых данных для обработки.
|
|
|
|
|
Apr 13 2016, 09:20
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(jcxz @ Apr 13 2016, 07:10)  PS: Контролировать размер стеков конечно нужно. И выделять под них память, а не надеяться что "что-то не налезет на что-то". Если опустить RTOSы и MMU/MPU.- а такие системы с супер циклом просты и весьма популярны, - то контроль стека организовать затратно, и риск проехать катком стека по переменным есть. Это неизбежно. На мой взгляд, в системе со стеком И кучей следует именну кучу выделять фиксированного размера, а стек - сколько есть памяти. Почему? Оценить потребность в стеке гораздо сложнее, чем в куче: прерывания, рекурсии, сложно-предсказуемые глубины вызовов... А вот работа с кучей более детерминирована и подконтрольна. Например, в тех немногих местах, где она используется, легко проверить полученный от malloc указатель на NULL и ругнуться, если что не так... Стек же я инициализирую на самый верхний адрес доступной RAM памяти. Как это в .COM программах в DOS делалось  (я стар, о я очень стар, я - суперстар!).
|
|
|
|
|
Apr 13 2016, 09:38
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (jcxz @ Apr 13 2016, 12:19)  И не убивать их когда работа закончена и создавать заново, а просто.... Когда о количестве ресурсов можно не думать, то оно, конечно, все "просто". Просто берем больше памяти, мегагерцев, размеров корпуса и батареи. QUOTE (jcxz @ Apr 13 2016, 12:25)  Если есть куда ругнуться. А если ни LCD ни UART с терминалом? Да и вообще - ближайший человек за тыщу км  Значит есть какая-то связь с чем-то, или человек за тысячу километров приедет хоть когда-то и увидит хоть в какой-то энергонезависимой памяти зафиксированную ошибку. Что уже позволит начать думать над тем, что в коде есть проблемы.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 13 2016, 09:41
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (KnightIgor @ Apr 13 2016, 12:20)  Стек же я инициализирую на самый верхний адрес доступной RAM памяти. Как это в .COM программах в DOS делалось  (я стар, о я очень стар, я - суперстар!). Я едва-ли Вас моложе, но так уже не делаю  , тем более, что не у x86 этих самых стеков чаще всего не один
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|