Май 012012
 

В этой статье будет рассмотрена организация памяти микроконтроллера, а также его внутренние шины. Сразу скажу, что никаких готовых проектов с программами здесь не ожидается, только голая матчасть, ну и пару строк кода для наглядности. Так что, работать с “железом” не придется. Думаю, что представление из каких “кирпичиков” построен фундамент, не помешает. Ведь даже при написании столь небольшого количества примеров кода для этого сайта, мне пару раз приходилось заглядывать в datasheet, чтобы посмотреть на карту памяти микроконтроллера.


Внутренние шины микроконтроллера.

System architecture

Как видно из рисунка, основа основ здесь — матрица шин Bus matrix.  К ней сходятся все остальные шины МК. Весь этот массив шин можно разделить на 2 класса. В первую очередь здесь выделяются 4 главные шины, которые в документации производителя классифицированы как “master”, то есть управляющие другими шинами. Это следующие шины:

  • ICode – шина команд. Соединяет ядро Cortex-M3 с матрицей шин Bus matrix. Назначение данной шины – извлекать инструкции из памяти (а здесь это может быть не только FLASH, но и SRAM) и передавать их ядру микроконтроллера для обработки.
  • DCode – шина данных. Передает ядру данные (например, константы или массивы данных из FLASH или SRAM), над которыми ядро потом производит какие-либо действия (арифметические, логические и т.п.). Или в обратную сторону, от ядра МК обратно в память.
  • System – используется для доступа к данным периферийных устройств или в SRAM. Периферия “висит” на шинах AHB/APB. Шина может использоваться также и для извлечения команд из SRAM, но эффективность работы в этом случае будет меньше, чем у шины команд ICode.
  • DMA – шина, используемая в режиме прямого доступа к памяти. С ее помощью можно быстро перегонять данные из периферии в память, периферии в периферию, памяти в память, памяти в периферию. В этом режиме передача данных происходит значительно быстрей, чем при выполнении программного кода, поскольку этим занимается отдельный контроллер DMA, он сам подключается к  нужным шинам и качает по ним данные, программный код при этом выполняется независимо. Более подробно с режимом DMA можно ознакомиться здесь STM32L. Контроллер DMA.

Следующие шины рангом пониже, чем предыдущие. Это шины типа “slave” – управляемые шинами “master”.

  • Шина FLASH–памяти (память программ и данных).
  • Шина SRAM–памяти (ОЗУ).
  • Шины периферийных устройств: AHB, APB1, APB2. Все периферийные устройства, находящиеся на этих шинах, после аппаратного сброса отключены от системы тактирования. Для работы с каким-либо модулем первоначально надо разрешить подачу к нему импульсов тактовой частоты.

Внутреннее пространство памяти.

Все адресное пространство может занимать вплоть до 4 Гигабайт, поскольку шины команд и данных здесь 32-разрядные. Естественно, что в данных микроконтроллерах мы такого объема памяти не увидим, неиспользуемые адреса считаются зарезервированными. Адресное пространство четко разделено на различные области памяти: память программ (FLASH), память EEPROM, память SRAM, регистры портов ввода-вывода и всех остальных периферийных устройств. Разбито все это пространство на 8 блоков по 512 Мегабайт. Посмотреть всю структуру памяти можно в datasheet в разделе Memory mapping. Здесь же опишу вкратце, естественно применительно к семейству STM32L.

  • С нулевого адреса начинается “смешанная” область памяти, задействованная под память программ или системную память, зависит от использования режима BOOT – автозагрузки.
  • С адреса 0x0800 0000 по адрес 0x0801 FFFF размещена FLASH-память программ.
  • 0x0808 0000 — 0x0808 FFFF – здесь EEPROM
  • С адреса 0x2000 0000 начинается SRAM
  • С адреса 0xE000 0000 размещены регистры периферийных устройств

Размеры областей памяти и набор периферийных устройств в пределах одного семейства могут отличаться, и надо не забывать об этом, но все начальные адреса заданы жестко. Наличие четко разделенного адресного пространства памяти программ и данных, а также раздельные шины команд и данных позволяет параллельно выполнять операции извлечения инструкций и данных. В отличие от предшествующих семейств ARM, Cortex-M3 построен по Гарвардской архитектуре.

Память SRAM может оперировать с 8-, 16- или 32-разрядными данными. Причем, также в отличие от предшественников, эти данные могут быть невыровненными — “фрагментированными”. Что это значит?

Допустим, создан массив из 4 элементов, каждый из них 8-разрядный.

uint8_t Array_1[4] = {X0, X1, X2, X3};

В одной 32-разрядной ячейке памяти эти данные будут размещены так

Невыровненные данные

Создадим другой массив address[4], он также будет из 4 элементов, но уже 32-разрядных, в него считаем адреса размещения элементов первого массива Array_1.

#include "inttypes.h" 

uint8_t Array_1[4] = {1, 2, 3, 4}; 
uint32_t address[4]; 
uint8_t i; 

int main()
 {
  for(i=0; i<4; i++)
   { 
    address[i] = (uint32_t)&Array_1[i];
   } 
  while(1);
 }

После выполнения программы, видим следующий результат в симуляторе IAR.

Невыровненный массив 1

Невыровненный массив 2

На скриншотах видно, что весь массив Array_1 разместился в одном 32-разрядном слове. Массив переменных address был создан для наглядности, в нем хорошо видно, что приращение адреса для элементов массива Array_1 составляет один байт. Оператор & при формировании массива address означает вовсе не логическую операцию И, здесь у него совершенно другой смысл – так мы “разыменуем” переменную Array_1[i], то есть получаем физический адрес ее размещения в памяти. Тема адресации и указателей довольно сложная для понимания, и объяснить ее “на пальцах” очень непросто, поэтому углубляться в нее здесь не будем.

А если бы возможности работать с “невыровненными” данными не было? Тогда бы все 8-разрядные элементы массива выравнивались по правому краю  в 32-разрядном слове, и получили бы мы 4 слова данных вместо одного, вот так

Выровненные данные

Как видите, в этом случае каждое 32-разрядное слово содержит всего один 8-битный элемент массива, остальные же 24 бита пропадают впустую. Чувствуете разницу?

В микроконтроллере предусмотрена возможность управления отдельными битами в пространстве памяти, так называемый “bit banding”. Вместо того, чтобы изменять отдельные биты с помощью накладывания “маски”, то есть выполнением последовательности операций “чтение-модификация-запись”, можно изменять содержимое намного быстрее. Это реализовано с помощью специальных областей памяти, позволяющих побитовую адресацию. Сюда входят области хранения бит и области доступа к битам. Выполняя операции с областью доступа, происходит обращение к фактическим адресам бит в памяти. Bit banding можно рассмотреть на примере работы с регистрами портов ввода-вывода GPIO. Для вывода данных в них используется регистр ODR, запись в который как раз производится через операции “чтение-модификация-запись” с использованием 16-разрядных значений. Но можно намного быстрее управлять отдельными битами этого регистра – через регистр побитовой установки/сброса выводов порта BSRR. Пример такого управления описан в статье STM32. Создание проекта в IAR EWARM. Работа с портами ввода/вывода. Часть 2.

FLASH память организована следующим образом:

  • До 128 КБайт памяти программ и 4 КБайт EEPROM
  • 4 КБайт системной памяти и 32 калибровочных байта

Интерфейс доступа к FLASH памяти имеет следующие особенности:

  • Операции чтения могут выполняться с данными (инструкциями) размерностью 32 или 64 бита.
  • Операции программирования/стирания
  • Защита от чтения/записи
  • Операции записи поддерживают разрядность данных 32 бита
  • Загрузка калибровочных байт после сброса
  • Работа в режимах малого потребления энергии

Память данных EEPROM разбита на 512 64-разрядных ячеек.

Память программ разделена на 32 сектора по 4 КБайт, каждый сектор далее делится еще на 16 страниц по 256 Байт. То есть, в общей сложности память программ может содержать до 512 страниц по 256 Байт.

В принципе, наверное и все пока. Вообще-то, работа с FLASH памятью заслуживает отдельной статьи. Довольно много тут возможностей. И еще есть встроенный Boot Loader для программирования FLASH, а также возможность выполнения программного кода из памяти SRAM. Если все это связать воедино, то темы будут уже для целого цикла статей.

Другие статьи:

  5 Responses to “STM32L. Пространство памяти и архитектура шин.”

  1. Хотелось бы узнать как обращаться к SRAM памяти без помощи DMA ( по uint8_t, uint16_t, uint32_t ) ? На примере UART, выделение в SRAM буфера определенного размера, и обращение к этому буферу из основной программы.

    • SRAM начинается с адреса 0x20000000. Можно адресовать по 8, 16, 32 бита, у Cortex такая адресация допустима. Если создать переменную или массив типа uintXX_t, то автоматически он разместится в памяти, начиная с этого адреса. Следующий массив или переменная пойдут за первым и т.д. Можно сделать через указатели, задав начальный адрес. Контролировать при отладке в IAR можно, открыв вкладку View->Memory и перейдя к нужному адресу.

    • А если открыть окно переменных View->Watch и прописать их, то можно будет увидеть и все адреса этих переменных или элементов массива.

  2. Здравствуйте, очень жду статью про FLASH память. Будет ли она рассматриваться ?