Что такое стек в МК?
Что такое стек?
вот задание: VI Динамические структуры 1. Дано неотрицательное число N и набор из N чисел. Создать.
Что такое стек?
Нигде не нашёл понятного определения некого стека. Что такое стек, как с ним работать и т.д.?
Что такое стек?
Объясните как они хранятся в памяти и что такое стек. Насколько я понял, стек это как стопка книг.
Что такое стек сопроцессора?
Преподаватель задал вопрос, что такое стек сопроцессора? никак не могу найти ответ на этот вопрос.
Что такое куча,стек,очередь?
Доброго Вам времени суток форумчане! Краткость сестра таланта, по этому сразу к делу. Объясните.
Сообщение от iman_094
Сообщение от iman_094
стека как такового на AVR нет
стек это организация данных по принципу "Последний пришел первый ушел"
Аппаратно такую организацию эти камни не поддерживают
для передачи аргументов в функцию и возврата значений используют регистры, о чем и написал raxp,
есть еще косвенная адресация, Z X Y которую с натяжкой можно назвать стеком
Добавлено через 11 минут
соврал ведь я
есть стек, по крайней мере есть команды push pop
а у каких камней был только аппаратный стек, для хранения адресов возврата, программно до него не достучатся?
Другими словами прерывание вызывает приостановку выполнения программы, командами push сохраняет контекст (состояние МК), выполняет программу обработки прерывания, командами pop восстанавливает контекст МК (короче делает как было до прерывания), программа продолжает выполняться дальше.
2. Сохранение адреса возврата при вызове подпрограмм. Когда МК встречает команду call, то переходит выполнять код по адресу указанном в данной команде, автоматически записывая в стек адрес следующий за call командой, встретив команду ret МК берет адрес на стеке и передаёт управление по нему.
Не по теме: Есть такая шутка, что на каждую улицу Пушкина в городе обязательно есть улица Попкина.
3. Сишные компиляторы очень любят использовать стек для разных вещей, например значение параметров в функцию передаётся через стек
Ну гдето так, что не написал старшие товарищи дополнят.
Добавлено через 23 минуты
Перечитал и понял, что не так ответил, верней надо было начать так:
Стек это область памяти, на адрес последнего значение указывает регистр МК SP (Stack Pointer)
При записи значения в стек командой push, адрес SP уменьшается (стек растет от старших адресов к младшим) и по новому адресу записывается значения, при команде pop передаётся значение по адресу указанному в SP и адрес SP автоматически увеличевается. Также запись\чтения значение в стек может происходить автоматически по управлению МК (вызов подпрограмм, вызов прерывания)
7. Виды памяти микроконтроллеров (на примере семейства avr). Стек и его инициализация.
В МК AVR реализована Гарвардская архитектура, в соответствии с которой разделены не только адресные пространства памяти программ и памяти данных, но также и шины доступа к ним.
Память программ: FLASH;
Память данных: оперативная память (ОЗУ) SRAM (Static RAM) и энергонезависимая память данных EEPROM.
Адресные пространства указанных видов памяти, как правило, разделены. Способы адресации и доступа к этим областям памяти также различны. Такая структура позволяет центральному процессору работать одновременно как с памятью программ, так и с памятью данных, что существенно увеличивает производительность. Каждая из областей памяти данных (SRAM и EEPROM) также расположена в своем адресном пространстве.
Обобщенная карта памяти AVR микроконтроллеров приведена на рисунке 1.

Рисунок 1 – Структура памяти МК AVR
Память программ
Память программ предназначена для хранения команд, управляющих функционированием микроконтроллера, также используется для хранения таблиц констант, не меняющихся во время работы программы.
Память программ представляет собой электрически стираемое программируемое постоянное запоминающее устройство (ППЗУ, FLASH ПЗУ). Так как длина всех команд кратна одному слову (16 бит), память программы имеет 16-разрядную организацию.
Логическая память программы разделена на две неравные части – область прикладной программы и область загрузчика. В последней может располагаться специальная программа, позволяющая микроконтроллеру самостоятельно управлять загрузкой и выгрузкой прикладных программ.
[Не знаю насколько это нужно писать в билете, но знать стоит…
Если возможность самопрограммирования не используется, то прикладная программа может располагаться и в области загрузчика.
Для адресации памяти программ используется счетчик команд. Размер счетчика команд составляет 12…16 разрядов, в зависимости от объема адресуемой памяти.
По адресу 0х0000 памяти программ находится вектор сброса. После инициализации МК (сброса) выполнение программы начинается с этого адреса. Начиная с адреса 0х0001 или 0х0002 памяти программ, располагается таблица векторов прерываний. Размер этой области зависит от МК.
При возникновении прерывания, после сохранения в стеке текущего значения счетчика команд, происходит выполнение команды, расположенной по адресу соответствующего вектора. Поэтому по данным адресам располагаются команды перехода к подпрограммам обработки прерываний.
Положение вектора сброса и таблицы векторов прерываний может быть перенесено из секции прикладных программ в секцию загрузчика.
В моделях с объемом памяти менее 8 Кбайт в качестве этих команд используются команды относительного перехода (RJMP), а в остальных моделях – команды абсолютного перехода (JMP).
В качестве промежуточных операторов используют 32 ячейки – оперативные регистры общего назначения (РОН). Доступ к этим ячейкам самый быстрый, а число операций с их содержимым наиболее разнообразное.
РОН делятся на три группы:
Младшие 0 – 15 обычные регистры общего назначения, в некоторым смысле неполноценные. С ними не работают многие команды (загрузка непосредственного числа).
Старшие 16 – 31 полноценные регистры, работающие со всеми командами.
Индексные 26 – 31 шесть последних регистров из старшей группы отличаются от остальных. Их можно использовать и как обычные регистры, но также они могут образовывать регистровые пары X(R26:R27), Y(R28:R29), Z(R30:R31), которые используются как указатели при работе с памятью …]
Память данных
Память данных разделена на 3 части:
оперативная память (статическое ОЗУ);
энергонезависимое EEPROM (ЭСППЗУ – электрически стираемое перепрограммируемое ПЗУ).
Регистровая память включает 32 РОН, объединенных в файл, и служебные регистры ввода/вывода (РВВ – регистры управления мк, регистры состояния). И те и другие расположены в адресном пространстве ОЗУ, но не являются его частью.
В старших моделях мк имеется область дополнительных (Extended) регистров ввода/вывода (ДРВВ). РВВ – 64 байта в памяти, ДРВВ – 160 байт. Введение дополнительных РВВ связано с тем, что для поддержки всех периферийных устройств этих моделей обычных 64 регистров недостаточно.
Оперативная память (ОЗУ), предназначенная для временного хранения переменных. Она есть не везде. Оперативная память представляет собой несколько сотен ячеек для временного хранения данных, от 64 байт до 4 килобайт, в зависимости от модели. В этих ячейках могут храниться любые данные, а доступ к ним осуществляется через команды LOAD и STORE.
Для некоторых микроконтроллеров возможна организация подключения внешнего статического ОЗУ объемом до 64К.
EEPROM-память предназначена для долговременного хранения различной информации, которая может изменяться в процессе функционирования микроконтроллерной системы. Все AVR имеют блок энергонезависимой электрически перезаписываемой памяти данных EEPROM от 512 Байт до 4 КБайт. Эта память расположена в отдельном адресном пространстве, а доступ к ней осуществляется с помощью определенных РВВ.
Этот тип памяти, доступный программе микроконтроллера непосредственно в ходе ее выполнения, удобен для хранения промежуточных данных, различных констант, коэффициентов, серийных номеров, ключей и т.п. EEPROM может быть загружена извне как через SPI интерфейс, так и с помощью обычного программатора. Число циклов стирание/запись — не менее 100 тыс.
Стек представляет собой область памяти, которую ядро МК использует для сохранения и восстановления адресов возврата из подпрограмм и прерываний. Практически у всех микроконтроллеров AVR стек размещается в оперативной памяти.
Для адресации текущего элемента (вершины стека) используется указатель стека SP (Stack Pointer). Это однобайтовый регистр ввода-вывода SPL у моделей с объемом памяти данных до 256 байт, или двухбайтовый SPH:SPL (SPH – старший байт, SPL – младший байт) у старших моделей с большим объемом памяти.
Так как после подачи напряжения питания (или после сброса) в регистрах содержится нулевое значение, в самом начале программы указатель стека необходимо проинициализировать, записав в него значение конечного адреса памяти данных.
Возврат из подпрограммы
1. Адрес команды, стоящей за командой вызова сохраняется в стеке
2. Значение указателя стека уменьшается на 2 байта
1. Адрес извлекается из стека
2. Загружается в счетчик команд
3. Значение указателя стека увеличивается на 2 байта
2 байта, так как для хранения счетчика команд требуется два байта.
То же происходит и во время вызова прерываний.
Схематичное расположение стека в памяти данных представлено на рисунке 2.
Рисунок 2 – Расположение стека в памяти данных
Во всех моделях AVR стек доступен со стороны пользовательской программы и может быть использован в процессе выполнения программы. Для работы со стеком существует всего две команды: занесение в стек (PUSH) и извлечение из стека (POP).
LDI R16, Low (RAMEND); устанавливаем SP = RAMEND
LDI R16, High (RAMEND)
RAMEND – это макроопределение, указывающее на конец ОЗУ для каждого конкретного мк.
Программист должен самостоятельно определить местоположение стека в самом начале программы. С точки зрения максимальной его глубины, вершину стека нужно поместить в самом конце SRAM, как это показано на рисунке 2.
Очень важно предварительно оценить максимальный размер стека (глубину стека). Может случиться так, что вершина стека поднимется слишком высоко и начнет “затирать” пользовательские данные, а это одна из самых сложно-выявляемых ошибок!
Стек AVR, помимо сохранения адресов возврата позволяет сохранять любые данные специально предназначенными для этого командами push Rr (загрузка в стек) и pop Rd (выгрузка из стека).
3.8. Стек и указатель стека
Стек необходим для запоминания адресов возврата из процедур обработки прерывания и подпрограмм. Его также можно использовать для временного хранения данных. Регистр указателя стека (SP) постоянно указывает на вершину стека. Он реализован в виде двух 8-битных регистров, доступных в пространстве памяти ввода-вывода. Данные помещаются в стек и извлекаются из него посредством инструкций PUSH и POP. Увеличение стека происходит в направлении от старших ячеек памяти к младшим. Таким образом, при помещении данных в стек содержимое регистра SP уменьшается, а при извлечении данных — увеличивается. После сброса, SP автоматически инициализируется значением, которое равно максимальному адресу внутреннего SRAM. При необходимости изменения SP нужно учитывать, что помещаемый в него адрес должен лежать выше 0x2000, а само изменение нужно выполнить перед вызовом каких-либо подпрограмм или разрешением прерываний.
При вызове подпрограмм или при переходе по вектору прерываний адрес возврата автоматически помещается в стек. Адрес возврата может быть представлен двумя или тремя байтами, что зависит от размера памяти микроконтроллера. У МК с памятью программ 128 кбайт и менее адрес возврата двухбайтный, поэтому, указатель стека декрементируется/инкрементируется на два. У тех же микроконтроллеров, которые оснащены памятью программ размером более 128 кбайт, адрес возврата трехбайтный, а декрементирование/инкрементирование SP выполняется на три. Адрес возврата извлекается из стека при выходе из прерывания по инструкции RETI, а из подпрограммы по инструкции RET.
Если инструкцией PUSH в стек помещаются данные, то SP декрементируется на единицу. Аналогичным образом, при извлечении данных из стека инструкцией POP содержимое SP инкрементируется на единицу.
Чтобы предотвратить сбой в выполнении программы при программном обновлении указателя стека, операция записи в SPL приводит к автоматическому отключению прерываний на время выполнения до четырех инструкций или до следующей операции записи в память ввода-вывода.
Азы распределения памяти и кода
Разбираемся как устроена память микроконтроллера на примере STM32F205VGT6.
Так же мы используем CubeMX для подготовки проекта.
Где хранятся данные , где стек, где код программы?
Генерим сначала пустой проект, оставляем только пустой main().
читаем ld файл
Linker script for STM32F205VG Device with ** 1024KByte FLASH, 128KByte RAM.
ld файл это основа, здесь CubeMx прописывает все исходные параметры памяти, стека, кода. Именно его надо спокойно/внимательно изучить, здесь все очевидно на самом деле.
Стек в микроконтроллерах на ядрах ARM растёт сверху вниз.
RAM по даташиту Up to 128 4 Kbytes of SRAM. То есть есть еще какие-то 4Kb SRAM в конце.
Стек располагается отдельно от остальных блоков памяти, в конце ОЗУ. Конец ОЗУ по мнению CubeMX это 0x20020000=..131072 примерно (128 4Kb).
Для контроля минимальных запасов стека и кучи в CubeMX есть такие установки
(_user_heap_stack = _Min_Heap_Size _Min_Stack_Size )
list полезный по информации файл на выходе сборки
.text — /* The program code and other data goes into FLASH */ , это скомпилированный машинный код — помещается во FLASH;
.data — /* Initialized data sections goes into RAM, load LMA copy after code */ — Переменные, это помещается в RAM; и зачем-то копия помещается еще во FLASH.
.rodata — /* Constant data goes into FLASH */ — аналог .data для неизменяемых данных, но помещается во FLASH;
.bss — /* Uninitialized data section */ , глобальные и статические переменные, которые при старте содержат нулевое значение — помещаются в RAM.
Момент истины
FLASH может содержать только неизменяемые данные , т.е. их нельзя в процессе исполнения перезаписать. (FLASH (rx) ) rx = read execute . Отсюда и идет весь этот винигред.
ld файл прописывает где и куда какие данные сохранить
>RAM — это помещается в RAM !
файл startup_stm32f205xx.s
Этот файл генерируется CubeMX. Он на ассемблере.
Смысл его в том, чтобы начать выполнение программы: для этого надо сначала установить указатель стека на начало стека :
Теперь для закрепления понимания поэкспериментируем
эффекта изменения распределения памяти не произойдет
сделаем так : char buf[10000]=<0>; — ничего не меняется
теперь в main сделаем так :
и .bss увеличивается с 00000020 до 00002730 (10032!) . То есть ушло в RAM!
теперь делаем так :
И .rodata увеличивается с 10 до 00002784 (10116) ! То есть ушло во FLASH (кстати только при условии явной инициализации=<0>).
Выводы такие :
Побольше const
Если RAM памяти не хватает или не хватает стека (он всегда есть часть RAM), то можно попробовать все что не меняется обозвать const , инициализировать обязательно и тогда это попадет не в RAM , а в FLASH.
section `._user_heap_stack’ will not fit in region `RAM’
Вот такая бяка появляется, когда RAM не хватает, например добавили нового кода , сторонние библиотеки .
У меня (на самом деле) эта ошибки ушла после удаления файла startupxxx.s и перегенерации заново проекта(и файла startup) из CubeMx.
Файлы для скачивания
* STM32F205VGT6_MemoryUsed [zip]
пустышка для изучения распределения памяти в контроллере STM32
