Программирование ARM-контроллеров STM32 на ядре Cortex-M3. Часть 3. Карта памяти контроллеров stm32, доступ к отдельным битам памяти

  1. Часть 1. Установка MDK, создание проекта, основы Keil uVision
  2. Часть 2. Команды и директивы ассемблера, структура и синтаксис программы. Первая программа для STM32.
  3. Часть 3. Карта памяти контроллеров STM32, доступ к отдельным битам памяти.
  4. Часть 4. Регистры, старт и режимы работы контроллеров STM32.
  5. Часть 5. Как залить прошивку в контроллер.
  6. Часть 6. Настройка системы тактирования.
  7. Часть 7. Работа с портами ввода-вывода.

Изучать архитектуру контроллеров stm32 мы начнём с их карты памяти. Зачем это надо? Ну, наверное, потому, что программа управления
контроллером записана в памяти, данные, которыми мы оперируем, находятся в памяти, различные регистры контроллера также спроецированы на определённые
адреса памяти. То есть чтобы работать с контроллером, нам просто необходимо знать что где расположено (по каким адресам) и как со всем этим
обращаться. Как раз в этом нам поможет карта памяти.

Разработчики ядра Cortex-M3 реализовали для него жёстко распределённое 4-х гигабайтное адресное пространство, которое в общем виде выглядит следующим образом:

Общий вид карты памяти для ядра Cortex-M3

  1. Код — эта область адресов используется для доступа к памяти, хранящей исполняемые коды.
  2. Внутреннее ОЗУ — по этим адресам доступна внутренняя оперативная память.
  3. Внутренняя периферия — по этим адресам доступны регистры управления внутренней периферией контроллера.
  4. Внешнее ОЗУ — эта область адресов используется для доступа к внешней оперативной памяти.
  5. Внешняя периферия — эта область адресов используется для доступа к внешней периферии.
  6. Системная область — по этим адресам доступно управление самим ядром.

Ещё раз скажу, что описанное выше распределение памяти определяется ядром Cortex-M3, — это то,
что получили для своих нужд разработчики контроллеров, решив отдать управление ими ядру Cortex-M3. Естественно,
что в конкретных линейках контроллеров есть свои нюансы распределения памяти, например, какие-то области могут не
использоваться, какие-то проецироваться одна на другую и так далее.

Карту памяти конкретного контроллера всегда можно найти в даташите на этот контроллер. А даташит,
как я уже говорил, всегда можно найти на вкладке «Books» менеджера проектов.

В общем виде карта памяти контроллеров STM32 выглядит так, как на рисунке ниже.

Общий вид карты памяти для контроллеров STM32

Регистры управления периферией контроллеров STM32F103

Вцелом, тут практически всё понятно, прояснения пожалуй требуют только два момента.

Во-первых, у вас наверняка возникает вопрос, — Что это за «псевдонимизируемая» область памяти?
Такое замысловатое название она получила потому, что я просто не знал как лучше перевести на русский язык выражение
aliasing area. Смысл тут в том, что в зависимости от выбранного способа загрузки (выбирается сочетанием уровней
сигналов на ногах boot0, boot1) эта область адресов может быть назначена псевдонимом flash-памяти или служебной
области памяти. Соответственно, обращение по этим адресам реально будет приводить к обращению во flash или в служебную область памяти.

Например, если сочетанием ног boot0, boot1 выбрана загрузка с flash, то
«псевдонимизируемая» область назначается псевдонимом flash-памяти, в результате чего flash-память становится
доступна сразу по двум диапазонам адресов — начиная с 0x00000000 и начиная с 0x08000000. То есть теперь
чтение/запись по адресу 0x00000000 приведёт к чтению/записи по адресу 0x08000000 (начало flash-памяти),
чтение/запись по адресу 0x00000004 — к чтению/записи по адресу 0x08000004 и так далее.

Во-вторых, хотелось бы по-подробнее рассмотреть две области адресов, — адреса, предназначенные для внутреннего ОЗУ и адреса, предназначенные для внутренней периферии.
Если вы ещё раз посмотрите на карту памяти контроллеров STM32, то увидите, что в каждой из этих областей есть диапазоны адресов, которые обозначены как «SRAM» и «регистры встроенной периферии
контроллера», а есть диапазоны адресов, про которые сказано, что они «используются для доступа к отдельным битам» SRAM и регистров встроенной периферии, соответственно.

Это специальная фишка для удобства операций с отдельными битами, которая называется bit-band. По сути она является всё той же псевдонимизацией, только теперь псевдоним по
другому адресу появляется не у байта или слова, а у каждого отдельного бита.

Зачем это надо? Традиционный способ изменить пару-тройку бит в байте, расположенном по определённому адресу, выглядит так: мы считываем нужный байт (слово / двойное слово) в
какой-нибудь регистр, меняем нужные биты (например, с помощью логических операций), а потом результат записываем из регистра назад, по тому же адресу. Этот способ называется
«чтение-модификация-запись».

В методе bit-band для каждого бита из области хранения данных есть псевдоним, обращаясь к которому можно сразу изменить нужный бит (операции «чтение-модификация-запись»
контроллер сделает автоматически, без нашего участия).

Область адресов, по которым данные доступны традиционным образом называется bit-band region (в русскоязычной терминологии — область хранения бит). Именно такие области и
подписаны на карте памяти как «SRAM» и «регистры встроенной периферии контроллера». Область адресов, в которой расположены псевдонимы отдельных бит из области хранения, называется bit-band alias
(псевдонимы области хранения). Про такие области, на карте памяти написано, что они используются для доступа к отдельным битам.

Можно заметить, что область псевдонимов для доступа к отдельным битам в 32 раза больше области хранения бит. Это объясняется тем, что в области псевдонимов значащими являются
только младшие биты каждого 32-х битного слова (именно они и являются псевдонимами отдельного бита из области хранения). Почему именно так? Потому что контроллер-то у нас 32-х битный и
оперировать мы всё равно будем 32-х битными словами, поэтому нужно, чтобы при изменении одного бита (а мы для этого будем писать в память целое 32-х битное слово) не затрагивались соседние биты.

Ну и самое интересное — каким образом вычислить адрес 32-х битного слова из области псевдонимов, младший бит которого является псевдонимом нужного нам бита из области
хранения? Делается это по следующей формуле:

AAW = SAR + OWBR * 0x20 + BN * 4 , где

AAW (Address of Alias World) — адрес слова, содержащего псевдоним нужного бита

SAR (Start of Alias Region) — начальный адрес области доступа к отдельным битам

OWBR (Offset of World in Bit-band Region) — смещение слова из области хранения, содеращего нужный бит, относительно начала области хранения

BN (Bit Number) — номер бита

Например, нам нужно установить в единицу 3-й бит в слове по адресу 0x20000008. Этот бит находится в SRAM, то есть начальный адрес области доступа к отдельным битам (SAR) у нас
будет равен 0x22000000. Смещение слова из области хранения, содержащего нужный бит, относительно начала области хранения (OWBR) будет равно 0x20000008 — 0x20000000 = 8. Номер бита (BN), как мы
уже сказали, равен 3.

Вычисляем адрес слова, которое содержит псевдоним нужного нам бита: AAW = 0x22000000 + 8 * 0x20 + 3 * 4 = 2200010C. Вот и всё, теперь записав по этому адресу любое слово,
содержащее в младшем бите единицу, мы фактически получим установку в единицу третьего бита в слове по адресу 0x20000008. Старшие биты записываемого слова, как я уже говорил, значения не
имеют. Если мы, наоборот, считываем слово из области доступа к отдельным битам, то старшие биты всегда читаются нулями.

На сегодня всё. А дальше мы поговорим о том, как контроллер стартует, о режимах его работы, о регистрах… ну и ещё о чём-нибудь.

  1. Часть 1. Установка MDK, создание проекта, основы Keil uVision
  2. Часть 2. Команды и директивы ассемблера, структура и синтаксис программы. Первая программа для STM32.
  3. Часть 3. Карта памяти контроллеров STM32, доступ к отдельным битам памяти.
  4. Часть 4. Регистры, старт и режимы работы контроллеров STM32.
  5. Часть 5. Как залить прошивку в контроллер.
  6. Часть 6. Настройка системы тактирования.
  7. Часть 7. Работа с портами ввода-вывода.

Добавить комментарий