Существуют разные сегменты памяти, в которые вводятся различные типы данных из кода C после компиляции. То есть: .text
, .data
, .bss
, стек и куча. Я просто хочу знать, где каждый из этих сегментов будет находиться в памяти микроконтроллера. То есть, какие данные поступают в какой тип памяти, учитывая типы памяти: RAM, NVRAM, ROM, EEPROM, FLASH и т. Д.
Я нашел ответы на подобные вопросы здесь, но они не смогли объяснить, каким будет содержимое каждого из различных типов памяти.
Любая помощь высоко ценится. Заранее спасибо!
microcontroller
c
embedded
memory
Соджу Т Варгезе
источник
источник
Ответы:
.текст
Сегмент .text содержит фактический код и запрограммирован во флэш-память для микроконтроллеров. При наличии нескольких несмежных блоков флэш-памяти может быть несколько текстовых сегментов; например, начальный вектор и векторы прерывания, расположенные в верхней части памяти, и код, начинающийся с 0; или отдельные разделы для начальной загрузки и основной программы.
.bss и .data
Существует три типа данных, которые могут быть размещены вне функции или процедуры; первая - это неинициализированные данные (исторически называемые .bss, которые также включают в себя 0 инициализированных данных), а вторая - инициализированные (не-bss) или .data. Название «bss» исторически происходит от «Block Started by Symbol», использовавшегося в ассемблере около 60 лет назад. Обе эти области области расположены в оперативной памяти.
По мере компиляции программы переменные будут распределены в одну из этих двух общих областей. На этапе связывания все элементы данных будут собраны вместе. У всех переменных, которые необходимо инициализировать, будет выделена часть памяти программы для хранения начальных значений, и непосредственно перед вызовом main () переменные будут инициализированы, как правило, модулем с именем crt0. Раздел bss инициализируется для всех нулей одним и тем же кодом запуска.
С несколькими микроконтроллерами есть более короткие инструкции, которые разрешают доступ к первой странице (первые 256 мест, иногда называемые страницей 0) ОЗУ. Компилятор для этих процессоров может зарезервировать ключевое слово, например,
near
для обозначения переменных, которые должны быть там размещены. Аналогичным образом, существуют также микроконтроллеры, которые могут ссылаться только на определенные области через регистр указателя (требующий дополнительных инструкций), и такие переменные обозначаютсяfar
. Наконец, некоторые процессоры могут обращаться к разделу памяти побитно, и компилятор может указать это (например, ключевое словоbit
).Поэтому могут быть дополнительные сегменты, такие как .nearbss и .neardata и т. Д., Где собираются эти переменные.
.rodata
Третий тип данных, внешний по отношению к функции или процедуре, похож на инициализированные переменные, за исключением того, что он предназначен только для чтения и не может быть изменен программой. В языке Си эти переменные обозначаются с помощью
const
ключевого слова. Они обычно хранятся как часть флеш-памяти программы. Иногда они идентифицируются как часть сегмента .rodata (данные только для чтения). На микроконтроллерах, использующих архитектуру Гарварда , компилятор должен использовать специальные инструкции для доступа к этим переменным.стек и куча
Стек и куча находятся в оперативной памяти. В зависимости от архитектуры процессора, стек может увеличиваться или уменьшаться. Если он вырастет, он будет размещен в нижней части оперативной памяти. Если он уменьшается, он будет помещен в конец ОЗУ. Куча будет использовать оставшуюся память, не выделенную для переменных, и расти в противоположном направлении стека. Максимальный размер стека и кучи обычно можно указать в качестве параметров компоновщика.
Переменные, помещенные в стек, - это любые переменные, определенные в функции или процедуре без ключевого слова
static
. Когда-то их называли автоматическими переменными (auto
ключевое слово), но это ключевое слово не нужно. Историческиauto
существует, потому что он был частью языка B, который предшествовал C, и там он был необходим. Параметры функции также помещаются в стек.Вот типичный макет для оперативной памяти (при условии отсутствия специального раздела на странице 0):
EEPROM, ROM и NVRAM
До появления флэш-памяти EEPROM (электрически стираемое программируемое постоянное запоминающее устройство) использовалось для хранения данных программы и const (сегменты .text и .rodata). Теперь имеется только небольшой объем (например, от 2 КБ до 8 КБ) EEPROM, если таковой вообще имеется, и он обычно используется для хранения данных конфигурации или других небольших объемов данных, которые необходимо сохранить при отключении питания. цикл. Они не объявляются в программе как переменные, а записываются в специальные регистры микроконтроллера. EEPROM также может быть реализован в виде отдельного чипа и доступен через шину SPI или I²C.
ПЗУ по сути такой же, как Flash, за исключением того, что он запрограммирован на заводе (не программируется пользователем). Он используется только для устройств с очень большим объемом.
NVRAM (энергонезависимая RAM) является альтернативой EEPROM и обычно реализуется как внешняя микросхема. Обычное ОЗУ может считаться энергонезависимым, если оно работает от батареи; в этом случае никаких специальных методов доступа не требуется.
Хотя данные могут быть сохранены во Flash, Flash-память имеет ограниченное количество циклов стирания / программирования (от 1000 до 10000), поэтому она не предназначена для этого. Это также требует одновременного удаления блоков памяти, поэтому неудобно обновлять всего несколько байтов. Он предназначен для кода и переменных только для чтения.
ЭСППЗУ имеет гораздо более высокие ограничения на циклы стирания / программирования (от 100 000 до 1 000 000), поэтому для этой цели гораздо лучше. Если на микроконтроллере имеется EEPROM, и он достаточно большой, это место, где вы хотите сохранить энергонезависимые данные. Однако вам также придется сначала стереть в блоках (обычно 4 КБ) перед записью.
Если EEPROM отсутствует или он слишком мал, тогда необходим внешний чип. ЭСППЗУ объемом 32 КБ составляет всего 66 ¢ и может быть стерто / записано до 1 000 000 раз. NVRAM с тем же числом операций стирания / программирования намного дороже (x10). NVRAM обычно быстрее для чтения, чем EEPROM, но медленнее для записи. Они могут быть записаны в один байт за раз или в блоках.
Лучшей альтернативой обоим из них является FRAM (сегнетоэлектрическое ОЗУ), который имеет практически бесконечные циклы записи (100 триллионов) и не имеет задержек при записи. Это примерно такая же цена, как у NVRAM, около 5 долларов за 32 КБ.
источник
Обычная встроенная система:
Кроме того, обычно есть отдельные сегменты флэш-памяти для кода запуска и векторов прерываний.
Объяснение:
Переменная имеет статическую продолжительность хранения, если она объявлена как
static
или если она находится в области видимости файла (иногда небрежно называемой «глобальной»). В C есть правило, гласящее, что все статические переменные продолжительности хранения, которые программист не инициализировал явно, должны быть обнулены.Каждая статическая переменная продолжительности хранения, которая инициализируется в ноль, неявно или явно, заканчивается в
.bss
. В то время как те, которые явно инициализированы ненулевым значением, заканчиваются в.data
.Примеры:
Пожалуйста, имейте в виду, что очень распространенная нестандартная установка для встроенных систем - это «минимальный запуск», что означает, что программа пропустит всю инициализацию объектов со статической продолжительностью хранения. Поэтому, возможно, было бы разумно никогда не писать программы, которые основаны на значениях инициализации таких переменных, а вместо этого устанавливают их в «время выполнения», прежде чем они будут использованы впервые.
Примеры других сегментов:
Переменные, которые могут помещаться в стек, часто могут оказаться в регистрах ЦП во время оптимизации. Как правило, любая переменная, у которой не взят адрес, может быть помещена в регистр процессора.
Обратите внимание, что указатели немного сложнее, чем другие переменные, поскольку они допускают два различных типа
const
, в зависимости от того, должны ли указывать данные только для чтения, или сам указатель должен быть. Очень важно знать разницу, чтобы ваши указатели не попали в оперативную память случайно, когда вы хотели, чтобы они были во флэш-памяти.В случае целочисленных констант, списков инициализаторов, строковых литералов и т. Д. Они могут оказаться в .text или .rodata в зависимости от компилятора. Вероятно, они заканчиваются как:
источник
.data
обычно имеет так называемый адрес загрузки во флэш-памяти, где хранятся начальные значения, и так называемый виртуальный адрес (не совсем виртуальный в микроконтроллере) в оперативной памяти, где переменная хранится во время выполнения. Передmain
запуском начальные значения копируются с адреса загрузки на виртуальный адрес. Вам не нужно хранить нули, поэтому.bss
не нужно хранить его начальные значения. sourceware.org/binutils/docs/ld/…Хотя любые данные могут помещаться в любую память, которую выбирает программист, обычно система работает лучше всего (и предназначена для использования), когда профиль использования данных сопоставляется с профилями чтения / записи памяти.
Например, программный код - WFRM (пишите мало, много читайте), и его очень много. Это хорошо подходит для FLASH. ROM OTOH является W раз RM.
Стек и куча небольшие, с большим количеством операций чтения и записи. Это лучше всего подходит для оперативной памяти.
ЭСППЗУ не подходит ни для одного из этих применений, но оно подходит для профиля небольших объемов данных, постоянных при включении питания, таких как пользовательские данные инициализации и, возможно, результаты регистрации.
источник