.текст
Сегмент .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 КБ.