22. Процесс начальной загрузки
В Главе 20 мы увидели, что обработчик исключения сброса Reset соответствует первой процедуре, которая должна быть выполнена при запуске ЦПУ. Фиксированная модель организации памяти процессоров на базе Cortex-M устанавливает, что адрес обработчика исключения сброса Reset размещается в памяти сразу после указателя основного стека (Main Stack Pointer, MSP), то есть по адресу 0x0000 0004 . Это расположение в памяти обычно соответствует началу Flash-памяти. Однако производители интегральных схем могут обойти это ограничение, «отражая (aliasing)» другие памяти на адрес 0x0000 0000 с помощью операции, называемой физическим перераспределением памяти. Данная операция выполняется аппаратно после нескольких тактовых циклов, и она отличается от перемещения таблицы векторов, рассмотренного в Главе 20 , которое выполняется с помощью того же кода, выполняемого на микроконтроллере.
Кроме того, платформа STM32 предоставляет предварительно запрограммированный на заводе загрузчик, который можно использовать для загрузки микропрограммы во Flashпамять из нескольких источников. В зависимости от семейства STM32 и используемого вида поставки микроконтроллер STM32 может загружать код с помощью коммуникационных периферийных устройств USART, USB, CAN, I²C и SPI. Загрузчик выбирается благодаря специальным загрузочным выводам (boot pins).
Данная глава завершает Главу 20 , демонстрируя процесс начальной загрузки (booting process), выполняемый микроконтроллерами STM32 после системного сброса. В ней дано подробное описание шагов, выполняемых во время начальной загрузки, и кратко показано, как использовать предварительно запрограммированный заводской загрузчик во всех микроконтроллерах STM32. В конечном счете, также показан пользовательский загрузчик, который позволяет обновить встроенное ПО с помощью интерфейса USART и специальной процедуры загрузки.
22.1. Единая система памяти Cortex-M и процесс начальной загрузки
В отличие от более продвинутых микропроцессорных архитектур, таких как ARM Cor- tex-A, микроконтроллеры Cortex-M не предоставляют модуль управления памятью (Memory Management Unit, MMU), который позволяет отразить (alias) логические адреса на фактические физические адреса. Это означает, что с точки зрения ядра Cortex-M карта памяти является фиксированной и стандартизированной среди всех реализаций.
В микроконтроллерах на базе Cortex-M область кода начинается с адреса 0x0000 0000 (доступ к которому осуществляется через шины I-Bus/D-Bus 1 в Cortex-M3/4/7 и через S-Bus в Cortex-M0/0+) в то время как область данных (SRAM) начинается с адреса 0x2000 0000 (доступ через S-Bus). Процессоры Cortex-M всегда выбирают таблицу
1 Для получения дополнительной информации об этих шинах см. Главу 9 .
Процесс начальной загрузки
векторов по шине I-Bus, что означает, что она загружается только из области кода (которая обычно соответствует Flash-памяти).
Микроконтроллеры STM32 реализуют специальный механизм, называемый физическим перераспределением памяти (physical remap), для выполнения начальной загрузки из других памятей помимо Flash-памяти, которое заключается в считывании двух специальных выводов микроконтроллера, называемых BOOT0 и BOOT1 2 . Электрическое состояние этих выводов определяет начальный адрес для начальной загрузки и, следовательно, память источника.
Таблица 1: Режимы начальной загрузки, доступные в микроконтроллере STM32F401RE
В таблице 1 показаны режимы начальной загрузки, доступные в микроконтроллере STM32F401RE, и она взята из соответствующего справочного руководства. Символ «х» в столбце BOOT1 означает, что, когда вывод BOOT0 подключен к земле, логическое состояние вывода BOOT1 может быть произвольным. Первая строка соответствует наиболее распространенному режиму начальной загрузки: микроконтроллер отразит Flashпамять на адрес 0x0000 0000 . Два других режима начальной загрузки соответствуют начальной загрузке с внутреннего SRAM и системной памяти – памяти ПЗУ, содержащей специальный загрузчик во всех микроконтроллерах STM32 и которую мы изучим чуть позже.
Состояние выводов BOOT защелкивается на 4-м фронте SYSCLK после сброса. После сброса пользователь может установить выводы BOOT для выбора необходимого режима начальной загрузки. Выводы BOOT также перепроверяются при выходе из режима ожидания с пониженным энергопотреблением. Следовательно, они должны быть сохранены в требуемой конфигурации режима начальной загрузки при переходе в режим ожидания. По истечении этого времени начального запуска ЦПУ выбирает указатель основного стека (MSP) с адреса 0x0000 0000 и запускает выполнение кода из загрузочной памяти, начиная с адреса 0x0000 0004 . Выбранная память (Flash, SRAM или ПЗУ) всегда доступна с ее оригинальным адресным пространством.
Если мы сконфигурируем микроконтроллер с начальной загрузкой из памяти SRAM, которая является энергозависимой памятью, мы должны загрузить программный код в эту память и убедиться, что действительная таблица векторов (по меньшей мере, состоящая из указателя основного стека и указателя на исключение сброса Reset) правильно
2 В зависимости от используемого корпуса в некоторых микроконтроллерах STM32 вывод BOOT1 отсутствует и заменяется специальным битом, называемым nBOOT1, внутри области байтов конфигурации. Обратитесь к справочному руководству по вашему микроконтроллеру для получения дополнительной информации об этом. В некоторых других семействах STM32, таких как STM32F7, функциональность вывода BOOT1 полностью заменена двумя специальными байтами конфигурации. Наконец, в тех микроконтроллерах, которые предоставляют два загрузочных вывода, BOOT0 в большинстве случаев является специализированным выводом, используемым исключительно для выбора источника начальной загрузки, в то время как BOOT1 используется совместно с выводом GPIO. После считывания BOOT1 соответствующий вывод GPIO освобождается и может использоваться для других целей. Однако существуют исключения среди микроконтроллеров с менее чем 36 выводами, где даже вывод BOOT0 считается входным GPIO, один раз считываемым в течение первых тактовых циклов (например, STM32L011K4T является одним из них).
Процесс начальной загрузки
установлена по адресу 0x0000 0000 . Это требуется для того, чтобы мы использовали инструмент отладчика, который предварительно загружает весь необходимый код внутрь SRAM перед началом выполнения. Кроме того, также необходим собственный скрипт компоновщика. Мы увидим полный пример позже.
22.1.1. Программное физическое перераспределение памяти
Как только микроконтроллер загружается, то есть выполняется исключение сброса Reset, все еще возможно перераспределить память, доступную через область кода (то есть через линии I-Bus и D-Bus), программируя некоторые биты регистра отображения памяти контроллера SYSCFG ( SYSCFG->MEMRMP в библиотеке CMSIS).
В зависимости от конкретного микроконтроллера STM32 могут быть перераспределены следующие памяти:
• Банк 1 FMC SDRAM
Последние две памяти доступны только в тех микроконтроллерах, которые предостав-
ляют контроллер внешней памяти (Flexible Memory Controller, FMC) – периферийное устройство, которое позволяет подключать внешние памяти NVM и SDRAM. В соответствии с таблицей 1, прямая начальная загрузка из внешней памяти NOR-Flash, а также из памяти SDRAM не допускается. Эти памяти могут отображаться по адресу 0x0000 0000
только при помощи программного физического перераспределения памяти, после того как микроконтроллер уже запущен с минимальной микропрограммой, загруженной из внутренней Flash-памяти.
После того, как внешняя память была физически перераспределена по адресу 0x0000 0000 , ЦПУ может получить к ней доступ по линиям I-Bus и D-Bus, а не по переполненной S-Bus, что повышает общую производительность. Это особенно важно для микроконтроллеров на базе Cortex-M7, где эти линии тесно связаны с выделенным кэшем L1.
Когда процессор выполняет начальную загрузку, содержимое регистра SYSCFG->MEMRMP привязывается к значениям выводов BOOT: это означает, что физическое перераспределение памяти автоматически выполняется из микроконтроллера при выборке выводов BOOT. Перед изменением содержимого этого регистра для выполнения перераспределения памяти важно иметь в целевой памяти рабочую таблицу векторов 3 .
22.1.2. Перемещение таблицы векторов
В Главе 20 мы увидели, как переместить таблицу векторов в CCM-память, чтобы мы могли воспользоваться преимуществами данной памяти. Когда мы выполняем физическое перераспределение памяти, устанавливая выводы BOOT, либо конфигурируя регистр SYSCFG->MEMRMP соответственно, нет необходимости выполнять перемещение таблицы
3 Важно уточнить, что ЦПУ не будет перезапускать последовательность сброса, вызывая обработчик исключения сброса Reset, после того как память была перераспределена с помощью регистра SYSCFG->MEMRMP . Вы будете нести ответственность за вызов этого обработчика исключений и за обеспечение того, чтобы ЦПУ был переведен в начальные условия, которые целевая микропрограмма ожидает найти (например, все периферийные устройства отключены и т. д.).
Процесс начальной загрузки
векторов, поскольку микроконтроллер автоматически присваивает начальный адрес 0x0000 0000 выбранной памяти. Иногда, однако, мы хотим переместить таблицу векторов в другие области памяти, которые не соответствуют ее источнику. Например, мы можем захотеть хранить два независимых образа микропрограммы во Flash-памяти (см. рисунок 1) и выбрать один из них в соответствии с заданным начальным условием. Это случай загрузчиков (bootloaders) – специальных «системных» программ, которые выполняют важные задачи конфигурации, такие как обновление основной микропрограммы, как мы увидим позже в данной главе.
Регистр смещения таблицы векторов (Vector Table Offset Register, VTOR) – это регистр в блоке управления системой (System Control Block, SCB) ( SCB->VTOR в библиотеке CMSIS), ко-
торый позволяет настроить базовый адрес таблицы векторов. Как только содержимое этого регистра будет установлено, ЦПУ будет обрабатывать адреса, начиная с новой базовой ячейки памяти, в качестве указателей на процедуры обслуживания прерываний.
Рисунок 1: Два независимых образа микропрограммы могут храниться во Flash-памяти
Boot memory selection stm32 для чего нужен
В этой статье дан обзор внутренней системы шин и памяти микроконтроллеров STM32F4 (перевод раздела «2 Memory and bus architecture» даташита [1]). Все непонятные термины и сокращения см. в Словарике [7].
[Архитектура системы]
STM32F405xx/07xx и STM32F415xx/17xx. Основная внутренняя система основана на 32-разрядной многослойной матрице шин AHB, которая соединяет:
• 8 главных устройств (master):
– Cortex®-M4 ядро с FPU I-bus, D-bus и S-bus
– шина памяти DMA1
– шина памяти DMA2
– шина периферийных устройств DMA2
– шина Ethernet DMA
– шина USB OTG HS DMA
• 7 подчиненных устройств (slave):
– шина внутренней памяти Flash ICode
– шина внутренней памяти Flash DCode
– основная внутренняя память SRAM1 (112 килобайт)
– дополнительная внутренняя память SRAM2 (16 килобайт)
– периферийные устройства AHB1, включая мосты AHB — APB и периферийные устройства APB
– периферийные устройства AHB2
– FSMC
Матрица шин предоставляет доступ от master к slave, позволяя реализовать конкурентный доступ и эффективную работу даже когда одновременно работают несколько высокоскоростных периферийных устройств. 64-килобайтная память данных CCM (Core Coupled Memory) не является частью матрицы шин, и к ней можно осуществлять доступ только через ядро CPU. Эта архитектура показана на рис. 1.
Рис. 1. Архитектура системы MCU STM32F405xx/07xx и STM32F415xx/17xx.
STM32F42xx и STM32F43xx. Основная внутренняя система основана на 32-разрядной многослойной матрице шин AHB, которая соединяет:
• 10 главных устройств (master):
– Cortex®-M4 ядро с FPU I-bus, D-bus и S-bus
– шина памяти DMA1
– шина памяти DMA2
– шина периферийных устройств DMA2
– шина Ethernet DMA
– шина USB OTG HS DMA
– шина DMA контроллера LCD [5]
– шина памяти DMA2D (Chrom-Art Accelerator™)
• 8 подчиненных устройств (slave):
– шина внутренней памяти Flash ICode – шина внутренней памяти Flash DCode
– основная внутренняя память SRAM1 (112 килобайт)
– дополнительная внутренняя память SRAM2 (16 килобайт)
– дополнительная внутренняя память SRAM3 (64 килобайта)
– периферийные устройства AHB1, включая мосты AHB — APB и периферийные устройства APB
– периферийные устройства AHB2
– FSMC
Матрица шин предоставляет доступ от master к slave, позволяя реализовать конкурентный доступ и эффективную работу даже когда одновременно работают несколько высокоскоростных периферийных устройств. 64-килобайтная память данных CCM (Core Coupled Memory) не является частью матрицы шин, и к ней можно осуществлять доступ только через ядро CPU. Эта архитектура показана на рис. 2.

Рис. 2. Архитектура системы MCU STM32F42xxx и STM32F43xxx.
I-bus. Эта шина соединяет с матрицей шин шину инструкций ядра Cortex®-M4. Шина I-bus используется ядром для выборки инструкций. Эта шина работает с памятью, где находится код (внутренняя память Flash/SRAM или внешние устройства памяти, доступные через контроллер FSMC/FMC).
D-bus. Эта шина соединяет память данных 64-килобайт CCM с шиной данных ядра Cortex®-M4 через матрицу шин (BusMatrix). Шина D-bus используется ядром для загрузки данных и доступа к отладке. Эта шина работает с памятью, где содержится код или данные (внутренняя память Flash или внешние устройства памяти, доступные через контроллер FSMC/FMC).
S-bus. Эта шина соединяет системную шину ядра Cortex®-M4 с BusMatrix. Шина S-bus используется для доступ к памяти, находящейся в периферийном устройстве или в SRAM. Через эту шину может также осуществляться выборка инструкций (с меньшей эффективностью по сравнению с ICode). Шина S-bus работает с внутренней памятью SRAM1, SRAM2 и SRAM3, периферийными устройствами AHB1, включая периферийные устройства APB, периферийные устройства AHB2 и внешние устройства памяти, доступные через контроллер FSMC/FMC.
Шина памяти DMA. Эта шина соединяет мастера шины памяти DMA с BusMatrix. Шина памяти DMA используется блоком DMA для выполнения перемещения данных между областями памяти. Эта шина работает со следующими областями данных: внутренние банки SRAM (SRAM1, SRAM2 и SRAM3) и внешние устройства памяти, доступные через контроллер FSMC/FMC.
Шина DMA периферийных устройств. Эта шина соединяет интерфейс мастера DMA периферии с BusMatrix. Шина DMA периферийных устройств используется блоком DMA для доступа к периферийным устройствам AHB, или для выполнения перемещений данных между областями памяти. Эта шина работает с периферийными устройствами AHB и APB плюс с памятью данных: внутренние банки SRAM (SRAM1, SRAM2 и SRAM3) и внешние устройства памяти, доступные через контроллер FSMC/FMC.
Шина Ethernet DMA. Эта шина соединяет интерфейс мастера Ethernet DMA с BusMatrix. Шина используется блоком Ethernet DMA для обмена данными с памятью. Шина Ethernet DMA работает с памятью данных: внутренние банки SRAM (SRAM1, SRAM2 и SRAM3), внутренняя память Flash и внешние устройства памяти, доступные через контроллер FSMC/FMC.
Шина USB OTG HS DMA. Эта шина соединяет интерфейс мастера USB OTG HS DMA с BusMatrix. Шина используется блоком USB OTG HS DMA для обмена данными с памятью. Шина USB OTG HS DMA работает с памятью данных: внутренние банки SRAM (SRAM1, SRAM2 и SRAM3), внутренняя память Flash и внешние устройства памяти, доступные через контроллер FSMC/FMC.
Шина DMA контроллера LCD-TFT. Эта шина соединяет интерфейс мастера DMA контроллера LCD [5] с BusMatrix. Шина используется блоком LCD-TFT DMA для обмена данными с памятью. Шина DMA контроллера LCD-TFT работает с памятью данных: внутренние банки SRAM (SRAM1, SRAM2 и SRAM3), внутренняя память Flash и внешние устройства памяти, доступные через контроллер FMC.
Шина DMA2D. Эта шина соединяет интерфейс мастера DMA2D с BusMatrix. Шина используется блоком графического ускорителя DMA2D для обмена данными с памятью. Шина DMA2D работает с памятью данных: внутренние банки SRAM (SRAM1, SRAM2 и SRAM3), внутренняя память Flash и внешние устройства памяти, доступные через контроллер FMC.
BusMatrix. Матрица шин управляет арбитражем между мастерами. Арбитраж использует алгоритм round-robin (циклическая передача приоритета).
Мосты AHB/APB. Два моста AHB/APB, APB1 и APB2, предоставляют полное синхронное соединение между шиной AHB и двумя шинами APB, что позволяет гибко выбирать частоту тактирования периферийных устройств. Для получения подробной информации по максимальным частотам шин APB1 и APB2 см. даташит на используемый MCU. В таблице 1 показано отображение адресов AHB и периферийных устройств APB.
После каждого сброса MCU тактирование всех периферийных устройств запрещено (кроме интерфейса памяти SRAM и Flash). Поэтому перед использованием периферийного устройства необходимо разрешить его тактирование программированием регистров контроллера RCC (RCC_AHBxENR или RCC_APBxENR).
Примечание: когда к регистру APB осуществляется 16-битный или 8-битный доступ, этот доступ преобразуется в 32-битный: мост дублирует 16-битные или 8-битные данные для подачи 32-битного вектора.
[Организация памяти]
Память программы, память данных, регистры и порты ввода/вывода организованы в одном общем, линейном пространстве адресов объемом 4 гигабайта.
Данные хранятся в памяти в формате little endian [6]. Байт с наименьшим номером в слове (с самым малым адресом) считается самым младшим значащим байтом этого слова. И наоборот, байт с самым большим номером (с самым большим адресом) считается самым значащим байтом слова.
Подробную информацию по адресам регистров периферийных устройств см. соответствующие разделы даташита [1].
Адресуемое пространство памяти поделено на 8 основных блоков, каждый по 512 мегабайт. Все области памяти, которые не принадлежат встроенным в чип областям памяти и периферийным устройствам считаются зарезервированными. См. карту памяти в даташите на используемый микроконтроллер.
[Карта памяти]
Подробную схему карты памяти см. в таблице, соответствующей вашему используемому MCU и периферийному устройству. Таблица 1 показывает границы адресов периферийных устройств, имеющихся во всех MCU STM32F4xx.
Таблица 1. Области адресов регистров STM32F4xx.
| Границы адресов | Периферийное устройство | Шина | Карта регистров (в даташите [1]) |
| 0xA0000000 — 0xA0000FFF | FSMC control register (STM32F405xx/07xx и STM32F415xx/17xx) / FMC control register (STM32F42xxx и STM32F43xxx) |
AHB3 | «36.6.9: FSMC register map», стр. 1600 «37.8: FMC register map», стр. 1680 |
| 0x50060800 — 0x50060BFF | RNG | AHB2 | «24.4.4: RNG register map», стр. 771 |
| 0x50060400 — 0x500607FF | HASH | «25.4.9: HASH register map», стр. 795 | |
| 0x50060000 — 0x500603FF | CRYP | «23.6.13: CRYP register map», стр. 763 | |
| 0x50050000 — 0x500503FF | DCMI | «15.8.12: DCMI register map», стр. 478 | |
| 0x50000000 — 0x5003FFFF | USB OTG FS | «34.16.6: OTG_FS register map», стр. 1326 | |
| 0x40040000 — 0x4007FFFF | USB OTG HS | AHB1 | «5.12.6: OTG_HS register map», стр. 1472 |
| 0x4002B000 — 0x4002BBFF | DMA2D | «11.5: DMA2D registers», стр. 352 | |
| 0x40028000 — 0x400293FF | ETHERNET MAC | «33.8.5: Ethernet register maps», стр. 1236 | |
| 0x40026400 — 0x400267FF | DMA2 | «10.5.11: DMA register map», стр. 335 | |
| 0x40026000 — 0x400263FF | DMA1 | ||
| 0x40024000 — 0x40024FFF | BKPSRAM | ||
| 0x40023C00 — 0x40023FFF | Регистры интерфейса Flash | «3.9: Flash interface registers» | |
| 0x40023800 — 0x40023BFF | RCC | «7.3.24: RCC register map», стр. 265 | |
| 0x40023000 — 0x400233FF | CRC | «4.4.4: CRC register map», стр. 115 | |
| 0x40022800 — 0x40022BFF | GPIOK | «8.4.11: GPIO register map», стр. 287 | |
| 0x40022400 — 0x400227FF | GPIOJ | ||
| 0x40022000 — 0x400223FF | GPIOI | «8.4.11: GPIO register map», стр. 287 | |
| 0x40021C00 — 0x40021FFF | GPIOH | ||
| 0x40021800 — 0x40021BFF | GPIOG | ||
| 0x40021400 — 0x400217FF | GPIOF | ||
| 0x40021000 — 0x400213FF | GPIOE | ||
| 0x40020C00 — 0x40020FFF | GPIOD | ||
| 0x40020800 — 0x40020BFF | GPIOC | ||
| 0x40020400 — 0x400207FF | GPIOB | ||
| 0x40020000 — 0x400203FF | GPIOA | ||
| 0x40016800 — 0x40016BFF | LCD-TFT | APB2 | «16.7.26: LTDC register map», стр. 512 |
| 0x40015800 — 0x40015BFF | SAI1 | «29.17.9: SAI register map», стр. 963 | |
| 0x40015400 — 0x400157FF | SPI6 | «28.5.10: SPI register map», стр. 925 | |
| 0x40015000 — 0x400153FF | SPI5 | ||
| 0x40014800 — 0x40014BFF | TIM11 | «19.5.12: TIM10/11/13/14 register map», стр. 694 | |
| 0x40014400 — 0x400147FF | TIM10 | ||
| 0x40014000 — 0x400143FF | TIM9 | «19.4.13: TIM9/12 register map», стр. 684 | |
| 0x40013C00 — 0x40013FFF | EXTI | «12.3.7: EXTI register map», стр. 387 | |
| 0x40013800 — 0x40013BFF | SYSCFG | «9.2.8: SYSCFG register map» для STM32F405xx/07xx и STM32F415xx/17xx стр. 294 «9.3.8: SYSCFG register map» для STM32F42xxx и STM32F43xxx стр. 301 |
|
| 0x40013400 — 0x400137FF | SPI4 | «28.5.10: SPI register map», стр. 925 | |
| 0x40013000 — 0x400133FF | SPI1 | ||
| 0x40012C00 — 0x40012FFF | SDIO | «31.9.16: SDIO register map», стр. 1074 | |
| 0x40012000 — 0x400123FF | ADC1, ADC2, ADC3 | «13.13.18: ADC register map», стр. 430 | |
| 0x40011400 — 0x400117FF | USART6 | «30.6.8: USART register map», стр. 1018 | |
| 0x40011000 — 0x400113FF | USART1 | ||
| 0x40010400 — 0x400107FF | TIM8 | «17.4.21: TIM1 and TIM8 register map», стр. 587 | |
| 0x40010000 — 0x400103FF | TIM1 | ||
| 0x40007C00 — 0x40007FFF | UART8 | APB1 | «30.6.8: USART register map», стр. 1018 |
| 0x40007800 — 0x40007BFF | UART7 | ||
| 0x40007400 — 0x400077FF | DAC | «14.5.15: DAC register map», стр. 453 | |
| 0x40007000 — 0x400073FF | PWR | «5.6: PWR register map», стр. 149 | |
| 0x40006800 — 0x40006BFF | CAN2 | «32.9.5: bxCAN register map», стр. 1118 | |
| 0x40006400 — 0x400067FF | CAN1 | ||
| 0x40005C00 — 0x40005FFF | I2C3 | «27.6.11: I2C register map», стр. 872 | |
| 0x40005800 — 0x40005BFF | I2C2 | ||
| 0x40005400 — 0x400057FF | I2C1 | ||
| 0x40005000 — 0x400053FF | UART5 | «30.6.8: USART register map», стр. 1018 | |
| 0x40004C00 — 0x40004FFF | UART4 | ||
| 0x40004800 — 0x40004BFF | USART3 | ||
| 0x40004400 — 0x400047FF | USART2 | ||
| 0x40004000 — 0x400043FF | I2S3ext | «28.5.10: SPI register map», стр. 925 | |
| 0x40003C00 — 0x40003FFF | SPI3 / I2S3 | ||
| 0x40003800 — 0x40003BFF | SPI2 / I2S2 | ||
| 0x40003400 — 0x400037FF | I2S2ext | ||
| 0x40003000 — 0x400033FF | IWDG | «21.4.5: IWDG register map», стр. 712 | |
| 0x40002C00 — 0x40002FFF | WWDG | «22.6.4: WWDG register map», стр. 719 | |
| 0x40002800 — 0x40002BFF | Регистры RTC и BKP | «26.6.21: RTC register map», стр. 836 | |
| 0x40002000 — 0x400023FF | TIM14 | «19.5.12: TIM10/11/13/14 register map», стр. 694 | |
| 0x40001C00 — 0x40001FFF | TIM13 | ||
| 0x40001800 — 0x40001BFF | TIM12 | «19.4.13: TIM9/12 register map», стр. 684 | |
| 0x40001400 — 0x400017FF | TIM7 | «20.4.9: TIM6 and TIM7 register map», стр. 707 | |
| 0x40001000 — 0x400013FF | TIM6 | ||
| 0x40000C00 — 0x40000FFF | TIM5 | «18.4.21: TIMx register map», стр. 648 | |
| 0x40000800 — 0x40000BFF | TIM4 | ||
| 0x40000400 — 0x400007FF | TIM3 | ||
| 0x40000000 — 0x400003FF | TIM2 |
Встроенная SRAM. В микроконтроллерах STM32F405xx/07xx и STM32F415xx/17xx имеется 4 килобайта Backup SRAM и 192 килобайта системной памяти SRAM. В микроконтроллерах STM32F42xxx и STM32F43xxx имеется 4 килобайта Backup SRAM и 192 килобайта системной памяти SRAM. Описание Backup SRAM см. в секции «5.1.2: Battery backup domain» даташита [1].
К встроенной SRAM можно обращаться как к байтам, половинкам слов (16 бит) или к полным словам (32 бита). Операции чтения и записи выполняются на полной скорости CPU без циклов задержек на ожидание (0 wait state). Встроенная SRAM поделена на 3 блока:
• SRAM1 и SRAM2, отображенная на адрес 0x20000000, и доступная для всех мастеров AHB.
• SRAM3 (имеется у STM32F42xxx и STM32F43xxx), отображенная на адрес 0x20020000, и доступная для всех мастеров AHB.
• CCM (Core Coupled Memory), отображенная на адрес 0x10000000, и доступная для CPU через D-bus.
Мастера AHB поддерживают конкурентные попытки доступа к SRAM (от Ethernet или USB OTG HS): например, Ethernet MAC может читать/записывать SRAM2, в то время как CPU читает/записывает SRAM1 или SRAM3.
CPU может обращаться к SRAM1, SRAM2 и SRAM3 через системную шину (System Bus) или через шины I-Code/D-Code, когда выбрана загрузка (boot) из SRAM, или когда выбрано физическое переназначение карты памяти (physical remap, см. секцию «9.2.1: SYSCFG memory remap register (SYSCFG_MEMRMP)» описания контроллера SYSCFG даташита [1]). Чтобы получить максимальную производительность выполнения кода из SRAM, должно быть выполнено physical remap (выбор кода boot или программы).
Память Flash. Интерфейс памяти Flash обслуживает доступ шин CPU AHB I-Code и D-Code к памяти Flash. Он реализован для операций стирания и программирования памяти Flash, и для механизмов защиты от чтения и записи. Интерфейс ускоряет выполнение кода с помощью предварительной выборки инструкции и линеек кеша.
Память Flash организована следующим образом:
• Основной блок памяти поделен на секторы.
• Системная память, из которой загружается система в режиме загрузки System memory boot mode.
• 512 байт OTP (однократно программируемая память) для данных пользователей.
• Байты опций, предназначенные для конфигурирования защиты чтения и записи, уровня детектора пропадания питания для сброса (BOR), программно/аппаратного сторожевого таймера и сброса, когда MCU находится в режиме Standby или Stop.
Подробнее см. секцию «3: Embedded Flash memory interface» в даташите [1].
Битовые операции (bit banding). Карта памяти Cortex®-M4 с FPU включает две группы бит (bit-band). Эти регионы отображают каждое слово ссылочного региона памяти на бит в группе (bit-band) памяти. Запись слова ссылочного региона дает тот же эффект, что и операция read-modify-write (чтение-модификация-запись) целевого бита группы bit-band.
В микроконтроллерах STM32F4xx как регистры периферийных устройств, так и SRAM, отображены на область bitband, поэтому дозволяются одиночные операции bit-band записи и чтения. Эти операции доступны только для доступа Cortex®-M4 с FPU, но не от других мастеров шины (например DMA).
Формула отображения показывает, как осуществляется ссылка на каждое слово в алиас-регионе на соответствующий бит группы в регионе bit-band:
bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number x 4)
bit_word_addr — адрес слова в алиас-регионе памяти, которая отображается на целевой бит.
bit_band_base — начальный адрес алиас-региона.
byte_offset — номер байта в регионе bit-band, который содержит целевой бит.
bit_number — позиция (0 .. 7) целевого бита.
Следующий пример показывает, как отображается бит 2 байта, находящегося в SRAM по адресу 0x20000300, на алиас-регион:
0x22006008 = 0x22000000 + (0x300*32) + (2*4)
Запись по адресу 0x22006008 дает тот же эффект, что и операция read-modify-write бита 2 байта SRAM по адресу 0x20000300.
Чтение адреса 0x22006008 возвратит значение бита 2 (0x01 или 0x00) байта по адресу 0x20000300 (0x01 бит установлен, 0x00 бит сброшен).
Подробнее про bit-banding см. руководство по программированию PM0214 [3].
[Конфигурация загрузки]
Из-за фиксированной карты памяти область кода (программа) начинается с адреса 0x00000000 (эта область памяти доступна через шины ICode/DCode), в то время как область данных (SRAM) начинается с адреса 0x20000000 (эта область доступна через системную шину). CPU Cortex®-M4 всегда делает выборку инструкции по вектору сброса на шине ICode. Это подразумевает, что область загрузки доступна только в области кода (обычно память Flash). Микроконтроллеры STM32F4xx реализуют специальный механизм, позволяющий загрузиться из других областей памяти (наподобие внутренней SRAM).
В STM32F4xx есть 3 разных режима загрузки, выбираемые ножками корпуса BOOT[1:0], что показано в таблице 2.
Таблица 2. Режимы загрузки.
| Выводы для выбора режима загрузки | Режим загрузки |
На что происходит ссылка |
|
| BOOT1 | BOOT0 | ||
| x | 0 | Основная память Flash | В качестве области загрузки выбрана основная память Flash. |
| 0 | 1 | Системная память | В качестве области загрузки выбрана System Memory. |
| 1 | 1 | Встроенная SRAM | В качестве области загрузки выбрана встроенная SRAM. |
Значения на выводах BOOTx защелкиваются на 4-ом фронте нарастания уровня тактов SYSCLK после сброса. Пользователь должен установить логический уровень ножек корпуса BOOT1 и BOOT0, чтобы после сброса был выбран необходимый режим загрузки.
Для функции BOOT0 выделена специальная ножка корпуса, в то время как функция BOOT1 совмещена с ножкой порта GPIO. Как только уровень BOOT1 был прочитан, соответствующая ножка GPIO освобождается, и может использоваться для других целей.
Уровни на ножках BOOT также анализируются, когда MCU выходит из режима Standby. Следовательно, необходимо сохранить требуемую конфигурацию режима загрузки, когда MCU находится в режиме Standby. После того, как задержка startup закончится, CPU делает выборку значение вершины стека по адресу 0x00000000, и затем начинает выполнять код из памяти загрузки (boot memory), начиная с 0x00000004.
Примечание: когда MCU загружается из SRAM, в коде инициализации приложения необходимо переразместить таблицу векторов в SRAM, используя таблицу исключений контроллера прерываний (NVIC exception table) и регистр смещения.
В случае, когда микроконтроллеры STM32F42xxx и STM32F43xxx загружаются из основной памяти Flash, программа приложения может загрузиться либо из банка 1, либо из банка 2. По умолчанию выбран банк 1.
Для выбора загрузки из банка 2 памяти Flash установите бит BFB2 в байтах опций пользователя. Когда этот бит установлен, и ножки управления загрузкой установлены на загрузку из основной памяти Flash, устройство загружается из системной памяти, и загрузчик делает безусловный переход на выполнение приложения пользователя, запрограммированного в банке 2 памяти Flash. Для дополнительной информации см. апноут AN2606 (для микроконтроллеров STM32F42xxx и STM32F43xxx см. статью [4]).
Встроенный загрузчик. Режим встроенного загрузчика используется для перепрограммирования памяти Flash, используя один из следующих последовательных интерфейсов:
• USART1 (ножки портов PA9/PA10)
• USART3 (ножки портов PB10/PB11 и PC10/PC11)
• CAN2 (ножки потов PB5 и PB13)
• USB OTG FS (ножки портов PA11/PA12) в режиме устройства USB (этот интерфейс обозначается аббревиатурой DFU: device firmware upgrade, обновление ПО устройства).
Периферийные устройства USART работают от внутреннего высокоскоростного RC-генератора 16 МГц (HSI), в то время как CAN и USB OTG FS требуют внешнего источника тактов (обычно это кварц, генератор HSE) с частой, нацело делящейся на 1 МГц (в диапазоне от 4 до 26 МГц).
Встроенный загрузчик находится в системной памяти, он программируется компанией ST в процессе производства. Для дополнительной информации см. апноут AN2606 (для микроконтроллеров STM32F42xxx и STM32F43xxx см. статью [4]).
Physical remap STM32F405xx/07xx и STM32F415xx/17xx. Как только выбрано состояние выводов управления загрузкой, программа приложения может изменить память, доступную в области кода (таким способом код может быть выполнен через шину ICode вместо того, чтобы выполняться через системную шину). Эта модификация выполняется программированием регистра переназначения памяти (SYSCFG memory remap register, SYSCFG_MEMRMP) контроллера SYSCFG, см. [1].
Переназначение (remap) может быть применено к следующим областям памяти:
• Основная память Flash
• Системная память
• Встроенная SRAM1 (112 килобайт)
• FSMC bank 1 (NOR/PSRAM 1 и 2)
Таблица 3. Отображение памяти при Boot mode/physical remap для STM32F405xx/07xx и STM32F415xx/17xx.
| Адреса | Boot/Remap в основную Flash |
Boot/Remap во встроенную SRAM |
Boot/Remap в System Memory |
Remap в FSMC |
| 0x2001C000 — 0x2001FFFF | SRAM2 (16 KB) | SRAM2 (16 KB) | SRAM2 (16 KB) | SRAM2 (16 KB) |
| 0x20000000 — 0x2001BFFF | SRAM1 (112 KB) | SRAM1 (112 KB) | SRAM1 (112 KB) | SRAM1 (112 KB) |
| 0x1FFF0000 — 0x1FFF77FF | System Memory | System Memory | System Memory | System Memory |
| 0x08100000 — 0x0FFFFFFF | Зарезервировано | Зарезервировано | Зарезервировано | Зарезервировано |
| 0x08000000 — 0x080FFFFF | Память Flash | Память Flash | Память Flash | Память Flash |
| 0x04000000 — 0x07FFFFFF | Зарезервировано | Зарезервировано | Зарезервировано | Зарезервировано |
| 0x00000000 — 0x000FFFFF (1)(2) | Ссылка на Flash (1 MB) | Ссылка на SRAM1 (112 KB) | Ссылка на System Memory (30 KB) |
Ссылка на FSMC bank 1 NOR /PSRAM 1 (128 MB) |
(1) Когда FSMC переназначен на адрес 0x00000000, могут быть переназначены только первые 2 региона банка 1 контроллера памяти (bank 1 NOR/PSRAM 1 и NOR/PSRAM 2). В режиме переназначения (remap mode), CPU может получить доступ к внешней памяти через шину ICode вместо системной шины, что улучшает производительность.
(2) Даже когда память ссылочно отображена на область загрузки (boot memory space), эта соответствующая память все еще доступна по своим оригинальным адресам на карте памяти.
Physical remap STM32F42xxx и STM32F43xxx. Как только выбрано состояние выводов управления загрузкой, программа приложения может изменить память, доступную в области кода (таким способом код может быть выполнен через шину ICode вместо того, чтобы выполняться через системную шину). Эта модификация выполняется программированием регистра переназначения памяти (SYSCFG memory remap register, SYSCFG_MEMRMP) контроллера SYSCFG, см. [1].
Переназначение (remap) может быть применено к следующим областям памяти:
• Основная память Flash
• Системная память
• Встроенная SRAM1 (112 килобайт)
• FSMC bank 1 (NOR/PSRAM 1 и 2)
• FMC SDRAM bank 1
Таблица 4. Отображение памяти при Boot mode/physical remap для STM32F42xxx и STM32F43xxx.
| Адреса | Boot/Remap в основную Flash |
Boot/Remap во встроенную SRAM |
Boot/Remap в System Memory |
Remap в FMC |
| 0x20020000 — 0x2002FFFF | SRAM3 (64 KB) | SRAM3 (64 KB) | SRAM3 (64 KB) | SRAM3 (64 KB) |
| 0x2001C000 — 0x2001FFFF | SRAM2 (16 KB) | SRAM2 (16 KB) | SRAM2 (16 KB) | SRAM2 (16 KB) |
| 0x20000000 — 0x2001BFFF | SRAM1 (112 KB) | SRAM1 (112 KB) | SRAM1 (112 KB) | SRAM1 (112 KB) |
| 0x1FFF0000 — 0x1FFF77FF | System Memory | System Memory | System Memory | System Memory |
| 0x08100000 — 0x0FFFFFFF | Зарезервировано | Зарезервировано | Зарезервировано | Зарезервировано |
| 0x08000000 — 0x080FFFFF | Память Flash | Память Flash | Память Flash | Память Flash |
| 0x04000000 — 0x07FFFFFF | Зарезервировано | Зарезервировано | Зарезервировано | Ссылка на FMC bank 1 NOR /PSRAM 2 (128 MB) |
| 0x00000000 — 0x001FFFFF (1)(2) | Ссылка на Flash (2 MB) | Ссылка на SRAM1 (112 KB) | Ссылка на System Memory (30 KB) |
Ссылка на FMC bank 1 NOR /PSRAM 1 (128 MB), или ссылка на FMC SDRAM bank 1 (128 MB) |
(1) Когда FSMC переназначен на адрес 0x00000000, могут быть переназначены только первые 2 региона банка 1 контроллера памяти (bank 1 NOR/PSRAM 1 и NOR/PSRAM 2) или SDRAM bank 1. В режиме переназначения (remap mode), CPU может получить доступ к внешней памяти через шину ICode вместо системной шины, что улучшает производительность.
(2) Даже когда память ссылочно отображена на область загрузки (boot memory space), эта соответствующая память все еще доступна по своим оригинальным адресам на карте памяти.
Boot memory selection stm32 для чего нужен
Например, начиная с флэш-памяти, в этом случае доступ к адресам 0x0 и 0x0800 0000 абсолютно одинаков.
Итак, после запуска cotex-M3 берет MSP с адреса 0x0, а ПК с адреса 0x4, что означает, что он принимает 0x8000000 и 0x08000004. Эквивалентны.
Однако запуск ОЗУ является исключением. 
Даже если мы выберем загрузку из ОЗУ, мы не сможем получить доступ с 0x2000 0000 до 0x0.
Как начинается ОЗУ?
3. Загрузка RAM
- Система не выполняет сопоставление от 0x2000 0000 до 0x0, но присваивает значения 0x2000 0000 и 0x20000004 SP и ПК при запуске с помощью внутреннего метода системы.
- Система выполняет сопоставление от 0x2000 0000 до 0x0 во время включения питания. После запуска (после включения MSP и ПК) сопоставление отключается, а затем два пространства открываются независимо.

3.2.1 Создание нового элемента проекта RAM
Найдите простой проект, который может стабильно работать на флеш-памяти, и создайте новый элемент проекта для запуска RAM. 
Значение установки этого элемента заключается в том, что измененная здесь конфигурация, глобальные макросы и т. д. не повлияют на конфигурацию флэш-памяти. Они независимы, и переключение очень удобно. 
После переключения вы увидите, что название проекта слева другое. 

Каждый должен заранее ознакомиться с настройкой загрузки флеш-памяти. 
Здесь мы переключаемся на загрузку из ОЗУ.
Сначала посмотрите на размер скомпилированного файла. 
Откройте файл карты 
можно увидеть
Размер созданного bin-файла составляет 5884 байта.
Таким образом, мы можем выделить в ПЗУ более 5884. 
Здесь тоже яма, это последнее слово.

3.2.4 Добавить глобальный макрос VECT_TAB_SRAM



ОЗУ нельзя запрограммировать на загрузку флеш-памяти таким образом, и нельзя ее перезапустить после выключения питания.
в основном работает в режиме отладки. 
После входа в отладку вы можете пошагово, на полной скорости и сбросить.
В Интернете есть сообщения о том, что они не могут сбросить настройки, но я с ними не сталкивался. Они могут работать нормально.
Иногда он будет нестабильным при запуске и выйдет из режима отладки при сообщении об ошибке, но его также можно использовать. 
Я долго бегал после просмотра картинки.
Когда я запускал ОЗУ, я вводил аппаратное исключение каждый раз, когда сталкивался с SystemInit, что меня очень расстраивало. Я чувствовал, что это ненормально, как только я нажимал на стек. Однако я был действительно подавлен, когда отслеживал изменения MSP в соответствии с моими ожиданиями. На выяснение причины ушло много времени.
Я видел этот абзац в китайском руководстве по stm32 раньше, 
stm32f103, который я использовал для тестирования, я думал, что RAM 64k, то есть 0x2000 0000
0x 2001 0000 .
На самом деле это совсем не так. ОЗУ stm32f103c8t6 составляет всего 20 КБ, поэтому пара операций SP является ненормальной и осуществляется доступ к недопустимому адресу.
После изменения размера это нормально. 
Boot memory selection stm32 для чего нужен


| Границы адресов | Периферийное устройство | Шина | Карта регистров (в даташите [1]) |
| 0xA0000000 — 0xA0000FFF | FSMC control register (STM32F405xx/07xx и STM32F415xx/17xx) / FMC control register (STM32F42xxx и STM32F43xxx) |
AHB3 | «36.6.9: FSMC register map», стр. 1600 «37.8: FMC register map», стр. 1680 |
| 0x50060800 — 0x50060BFF | RNG | AHB2 | «24.4.4: RNG register map», стр. 771 |
| 0x50060400 — 0x500607FF | HASH | «25.4.9: HASH register map», стр. 795 | |
| 0x50060000 — 0x500603FF | CRYP | «23.6.13: CRYP register map», стр. 763 | |
| 0x50050000 — 0x500503FF | DCMI | «15.8.12: DCMI register map», стр. 478 | |
| 0x50000000 — 0x5003FFFF | USB OTG FS | «34.16.6: OTG_FS register map», стр. 1326 | |
| 0x40040000 — 0x4007FFFF | USB OTG HS | AHB1 | «5.12.6: OTG_HS register map», стр. 1472 |
| 0x4002B000 — 0x4002BBFF | DMA2D | «11.5: DMA2D registers», стр. 352 | |
| 0x40028000 — 0x400293FF | ETHERNET MAC | «33.8.5: Ethernet register maps», стр. 1236 | |
| 0x40026400 — 0x400267FF | DMA2 | «10.5.11: DMA register map», стр. 335 | |
| 0x40026000 — 0x400263FF | DMA1 | ||
| 0x40024000 — 0x40024FFF | BKPSRAM | ||
| 0x40023C00 — 0x40023FFF | Регистры интерфейса Flash | «3.9: Flash interface registers» | |
| 0x40023800 — 0x40023BFF | RCC | «7.3.24: RCC register map», стр. 265 | |
| 0x40023000 — 0x400233FF | CRC | «4.4.4: CRC register map», стр. 115 | |
| 0x40022800 — 0x40022BFF | GPIOK | «8.4.11: GPIO register map», стр. 287 | |
| 0x40022400 — 0x400227FF | GPIOJ | ||
| 0x40022000 — 0x400223FF | GPIOI | «8.4.11: GPIO register map», стр. 287 | |
| 0x40021C00 — 0x40021FFF | GPIOH | ||
| 0x40021800 — 0x40021BFF | GPIOG | ||
| 0x40021400 — 0x400217FF | GPIOF | ||
| 0x40021000 — 0x400213FF | GPIOE | ||
| 0x40020C00 — 0x40020FFF | GPIOD | ||
| 0x40020800 — 0x40020BFF | GPIOC | ||
| 0x40020400 — 0x400207FF | GPIOB | ||
| 0x40020000 — 0x400203FF | GPIOA | ||
| 0x40016800 — 0x40016BFF | LCD-TFT | APB2 | «16.7.26: LTDC register map», стр. 512 |
| 0x40015800 — 0x40015BFF | SAI1 | «29.17.9: SAI register map», стр. 963 | |
| 0x40015400 — 0x400157FF | SPI6 | «28.5.10: SPI register map», стр. 925 | |
| 0x40015000 — 0x400153FF | SPI5 | ||
| 0x40014800 — 0x40014BFF | TIM11 | «19.5.12: TIM10/11/13/14 register map», стр. 694 | |
| 0x40014400 — 0x400147FF | TIM10 | ||
| 0x40014000 — 0x400143FF | TIM9 | «19.4.13: TIM9/12 register map», стр. 684 | |
| 0x40013C00 — 0x40013FFF | EXTI | «12.3.7: EXTI register map», стр. 387 | |
| 0x40013800 — 0x40013BFF | SYSCFG | «9.2.8: SYSCFG register map» для STM32F405xx/07xx и STM32F415xx/17xx стр. 294 «9.3.8: SYSCFG register map» для STM32F42xxx и STM32F43xxx стр. 301 |
|
| 0x40013400 — 0x400137FF | SPI4 | «28.5.10: SPI register map», стр. 925 | |
| 0x40013000 — 0x400133FF | SPI1 | ||
| 0x40012C00 — 0x40012FFF | SDIO | «31.9.16: SDIO register map», стр. 1074 | |
| 0x40012000 — 0x400123FF | ADC1, ADC2, ADC3 | «13.13.18: ADC register map», стр. 430 | |
| 0x40011400 — 0x400117FF | USART6 | «30.6.8: USART register map», стр. 1018 | |
| 0x40011000 — 0x400113FF | USART1 | ||
| 0x40010400 — 0x400107FF | TIM8 | «17.4.21: TIM1 and TIM8 register map», стр. 587 | |
| 0x40010000 — 0x400103FF | TIM1 | ||
| 0x40007C00 — 0x40007FFF | UART8 | APB1 | «30.6.8: USART register map», стр. 1018 |
| 0x40007800 — 0x40007BFF | UART7 | ||
| 0x40007400 — 0x400077FF | DAC | «14.5.15: DAC register map», стр. 453 | |
| 0x40007000 — 0x400073FF | PWR | «5.6: PWR register map», стр. 149 | |
| 0x40006800 — 0x40006BFF | CAN2 | «32.9.5: bxCAN register map», стр. 1118 | |
| 0x40006400 — 0x400067FF | CAN1 | ||
| 0x40005C00 — 0x40005FFF | I2C3 | «27.6.11: I2C register map», стр. 872 | |
| 0x40005800 — 0x40005BFF | I2C2 | ||
| 0x40005400 — 0x400057FF | I2C1 | ||
| 0x40005000 — 0x400053FF | UART5 | «30.6.8: USART register map», стр. 1018 | |
| 0x40004C00 — 0x40004FFF | UART4 | ||
| 0x40004800 — 0x40004BFF | USART3 | ||
| 0x40004400 — 0x400047FF | USART2 | ||
| 0x40004000 — 0x400043FF | I2S3ext | «28.5.10: SPI register map», стр. 925 | |
| 0x40003C00 — 0x40003FFF | SPI3 / I2S3 | ||
| 0x40003800 — 0x40003BFF | SPI2 / I2S2 | ||
| 0x40003400 — 0x400037FF | I2S2ext | ||
| 0x40003000 — 0x400033FF | IWDG | «21.4.5: IWDG register map», стр. 712 | |
| 0x40002C00 — 0x40002FFF | WWDG | «22.6.4: WWDG register map», стр. 719 | |
| 0x40002800 — 0x40002BFF | Регистры RTC и BKP | «26.6.21: RTC register map», стр. 836 | |
| 0x40002000 — 0x400023FF | TIM14 | «19.5.12: TIM10/11/13/14 register map», стр. 694 | |
| 0x40001C00 — 0x40001FFF | TIM13 | ||
| 0x40001800 — 0x40001BFF | TIM12 | «19.4.13: TIM9/12 register map», стр. 684 | |
| 0x40001400 — 0x400017FF | TIM7 | «20.4.9: TIM6 and TIM7 register map», стр. 707 | |
| 0x40001000 — 0x400013FF | TIM6 | ||
| 0x40000C00 — 0x40000FFF | TIM5 | «18.4.21: TIMx register map», стр. 648 | |
| 0x40000800 — 0x40000BFF | TIM4 | ||
| 0x40000400 — 0x400007FF | TIM3 | ||
| 0x40000000 — 0x400003FF | TIM2 |
bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number x 4)
0x22006008 = 0x22000000 + (0x300*32) + (2*4)
| Выводы для выбора режима загрузки | Режим загрузки |
На что происходит ссылка |
|
| BOOT1 | BOOT0 | ||
| x | 0 | Основная память Flash | В качестве области загрузки выбрана основная память Flash. |
| 0 | 1 | Системная память | В качестве области загрузки выбрана System Memory. |
| 1 | 1 | Встроенная SRAM | В качестве области загрузки выбрана встроенная SRAM. |
| Адреса | Boot/Remap в основную Flash |
Boot/Remap во встроенную SRAM |
Boot/Remap в System Memory |
Remap в FSMC |
| 0x2001C000 — 0x2001FFFF | SRAM2 (16 KB) | SRAM2 (16 KB) | SRAM2 (16 KB) | SRAM2 (16 KB) |
| 0x20000000 — 0x2001BFFF | SRAM1 (112 KB) | SRAM1 (112 KB) | SRAM1 (112 KB) | SRAM1 (112 KB) |
| 0x1FFF0000 — 0x1FFF77FF | System Memory | System Memory | System Memory | System Memory |
| 0x08100000 — 0x0FFFFFFF | Зарезервировано | Зарезервировано | Зарезервировано | Зарезервировано |
| 0x08000000 — 0x080FFFFF | Память Flash | Память Flash | Память Flash | Память Flash |
| 0x04000000 — 0x07FFFFFF | Зарезервировано | Зарезервировано | Зарезервировано | Зарезервировано |
| 0x00000000 — 0x000FFFFF (1)(2) | Ссылка на Flash (1 MB) | Ссылка на SRAM1 (112 KB) | Ссылка на System Memory (30 KB) |
Ссылка на FSMC bank 1 NOR /PSRAM 1 (128 MB) |
| Адреса | Boot/Remap в основную Flash |
Boot/Remap во встроенную SRAM |
Boot/Remap в System Memory |
Remap в FMC |
| 0x20020000 — 0x2002FFFF | SRAM3 (64 KB) | SRAM3 (64 KB) | SRAM3 (64 KB) | SRAM3 (64 KB) |
| 0x2001C000 — 0x2001FFFF | SRAM2 (16 KB) | SRAM2 (16 KB) | SRAM2 (16 KB) | SRAM2 (16 KB) |
| 0x20000000 — 0x2001BFFF | SRAM1 (112 KB) | SRAM1 (112 KB) | SRAM1 (112 KB) | SRAM1 (112 KB) |
| 0x1FFF0000 — 0x1FFF77FF | System Memory | System Memory | System Memory | System Memory |
| 0x08100000 — 0x0FFFFFFF | Зарезервировано | Зарезервировано | Зарезервировано | Зарезервировано |
| 0x08000000 — 0x080FFFFF | Память Flash | Память Flash | Память Flash | Память Flash |
| 0x04000000 — 0x07FFFFFF | Зарезервировано | Зарезервировано | Зарезервировано | Ссылка на FMC bank 1 NOR /PSRAM 2 (128 MB) |
| 0x00000000 — 0x001FFFFF (1)(2) | Ссылка на Flash (2 MB) | Ссылка на SRAM1 (112 KB) | Ссылка на System Memory (30 KB) |
Ссылка на FMC bank 1 NOR /PSRAM 1 (128 MB), или ссылка на FMC SDRAM bank 1 (128 MB) |
STM32 Jump to System Memory Bootloader
All STM32 MCUs has a builtin bootloader stored in so-called system memory. The system memory is a ROM (read-only memory) which is created during the production of the MCU and can never be changed (it can however be disabled — see Read Out Protection). When the MCU startup the Boot0 pin is asserted and if high (pulled up to VCC) the MCU will execute the bootloader.
Contents
The «problem» (or challenge)
But what if we would like to execute this bootloader programmatically based on some other event for example the press of a user button or a command in a serial console. While this is entirely possible it is surprisingly difficult. The problem is that the built-in bootloader make a lot of assumptions and it is necessary to make certain all these assumptions are met before jumping to it. In general that would look something like:
- Find system memory location for specific STM32 in AN2606 (see Miscellaneous Links)
- Set RCC to default values (the same as on startup) [Internal clock, no PLL, etc.)
- Disable SysTick interrupt and reset it to default
- Disable all interrupts
- Map system memory to 0x00000000 location
- Set jump location to memory location + 4 bytes offset
- Set main stack pointer to value stored at system memory location address
- Call virtual function assigned before
Depending on which peripherals is being used, the above can be quite complicated and changes in code can easily screw this up.
The easy solution
Fortunately, there is in fact an easier way to do this. If we look at the code generated by STM32CubeMX the startup is like this:
By the time the main function is being called, only the memory has been initialized (BSS has been set to 0x00 throughout), and if we were to do the jump immediately (in the USER CODE BEGIN 1 section) that would work just fine. That would look something like this:
Of course the result of that would be an application that always executed the bootloader, and that is not really useful, nor is it what we wanted to do.
What we need is a way to store a flag, which will survive a system restart of the MCU. This is a little bit tricky since the user memory (RSS) is set to zero during restart. There are multiple examples online of how to store variables/flags which will survive a processor reset. A common approach is to use the user registers of the Real Time Clock (RTC), however this approach is quite complicated (require the RTC to be initialized) and it is quite hard to make it generic for all STM32s since the RTC differs quite a lot between the STM32 variants.
Fortunately there’s a hack which can be utilized here. If we look at the memory (RAM) of a typical STM32 application it looks something like:

The DATA and RSS are being reset during restart, but everything above that (heap + stack) are being left alone. Not only is it being left alone, but we got variables from the linker which tells us exactly where they are independent of the actual MCU. Looking at a typical linker script (generated by STM32CubeMX we will find the following:
In other word, the _estack points to the highest memory location (the stack grows down, while the heap grows up).
Of course under «normal» circumstances one shouldn’t mess with the stack, but in our case immediately after messing with it we perform a system reset, so we can afford to lose whatever is stored somewhere in the stack. If we debug the application the MCU registers contain the following at the start of the main function:

The interesting register here is the stack pointer SP which contains 0x2001fff0. The highest RAM address on the particular MCU used in this example (Black Pill STM32F411) is 0x2001ffff, so the stack at this point have used about 15 bytes. Any value after that (remember the stack grow down, so lower address) will be unused at this point. If we create a pointer like this:
we can store a «known» value at that location, reset the MCU and then check that value immediately at startup.
Our initial code shown earlier can now be expanded like this:
If our bootloader flag contains anything but BOOTLOADER_FLAG_VALUE, the application will move on with it’s normal initialization of interrupts, timers, peripherals etc., but IF our flag contains BOOTLOADER_FLAG_VALUE it will jump — successfully — to the internal bootloader. Triggering this with a user button could look like this:
In this case, if a button connected to BTN_Pin is pressed for more than 1 second, the device will reboot in bootloader mode.
Evaluation
Now, I am fully aware that messing with the stack like I do in this example is quite naughty. The question is, is there any way this could go wrong. Well, the answer is a «yes» but unlikely. If we look at the point where we do mess with the stack, it looks like this:
I guess that if a interrupt happened between setting the bootloader flag and calling the reset something unexpected could happen. Also a possible issue would be if the HAL_NVIC_SystemReset function call pushed the return address pushed to the stack would be at the exact offset location. This might require a bit more analysis.
Boot memory selection stm32 для чего нужен
[Note: Learn the STM32 summary of the notes, do not spray. There are still some shortcomings.
—— This article is reproduced from the original, infringement, please contact the author, thank you. 】
Original blog address:
First, three BOOT mode introduction
The so-called startup, generally means that after we have a good program, when the chip is restarted, the fourth rising edge of SYSCLK, the value of the BOOT pin will be latched. The user can select the startup mode after reset by setting the state of the BOOT1 and BOOT0 pins. 
Main Flash memory
is the built-in Flash of STM32. Generally, when we use JTAG or SWD mode to download the program, it is downloaded to this, and it will start the program directly after restarting.
System memory
Boot from system memory, the program function started in this mode is set by the manufacturer. In general, this type of startup is used less. The system memory is a specific area inside the chip. When the STM32 is shipped from the factory, the ST presets a BootLoader inside the area. This is the ISP program we often say. This is a ROM.
cannot be modified after shipment. Generally speaking, when we use this startup mode, we download the program from the serial port. Because the BootLoader provided by the manufacturer provides the firmware of the serial download program, the program can be downloaded to the system Flash through the BootLoader. But this download method requires the following steps:
Step1: Set BOOT0 to 1, BOOT1 to 0, and then press the reset button to start BootLoader from system memory.
Step2: Finally, with the help of BootLoader, download the program to Flash through the serial port.
Step3: After the program download is completed, it is necessary to set BOOT0 to GND and reset manually. In this way, STM32 can be booted from Flash and can be seen. , need to jump over the cap to jump, very do not pay attention to the user experience.
Embedded Memory
Built-in SRAM, since it is SRAM, naturally there is no program storage capability. This mode is generally used for program debugging. If I only modified a small place in the code, then I need to erase the entire Flash again. The time-consuming comparison can be considered to start the code from this mode (that is, the memory of STM32) for fast program debugging, etc. After the program debugging is completed, the program is downloaded to the SRAM.
Second, develop BOOT mode selection.
1, usually use the program code stored in the main flash memory, configuration mode: BOOT0 = 0, BOOT1 = X;
2, Flash lock solution:
During the development and debugging process, the internal flash is locked for some reason, the SWD and Jtag debugging cannot be connected, and the device cannot be read. The code can be rewritten by modifying the BOOT mode.
Modified to BOOT0=1, BOOT1=0 can be booted from the system memory, ST comes with the Bootloader program, SWD and JTAG debug interface are dedicated. After re-programming, you can change the BOOT mode to BOOT0=0, BOOT1=X to use normally.
———————————————- Reproduce the summary article, If there is any infringement, please contact the author to delete, thank you.
Русские Блоги
[Stm32] Глубокие размышления о запуске оперативной памяти stm32 (2)
1. Введение
В прошлой статье был сделан завершающий анализ процесса запуска системы stm32, и мы рассмотрели выбор и принцип работы режима запуска stm32. Я также столкнулся с некоторыми вещами, которых не понимал, поэтому начал экспериментировать и записывать это здесь.
2. Три режима запуска
В настоящее время stm32 поддерживает 3 режима запуска.
| BOOT0 | BOOT1 | Режим запуска | Начальный адрес |
|---|---|---|---|
| 0 | x | flash | 0x0800 0000 |
| 1 | 0 | Системная память | 0x1FF00000 |
| 1 | 1 | RAM | 0x2000 0000 |
Начиная с флэш-памяти и системной памяти, система выполнит сопоставление адресов.
STM32 рассматривает область от 0x00000000 до 0x0005FFFF как область псевдонима загрузочного пространства.
Например, начиная с флэш-памяти, в этом случае доступ к адресам 0x0 и 0x0800 0000 абсолютно одинаков.
Итак, после запуска cotex-M3 берет MSP с адреса 0x0, а ПК с адреса 0x4, что означает, что он принимает 0x8000000 и 0x08000004. Эквивалентны.
Однако запуск ОЗУ является исключением.
Даже если мы выберем загрузку из ОЗУ, мы не сможем получить доступ с 0x2000 0000 до 0x0.
Как начинается ОЗУ?
3. Загрузка RAM
3.1 Принцип
Прежде всего, мы знаем, что когда boot0 = 1, boot1 = 1, то есть при запуске RAM, cotex-m3 должен принимать msp из 0x0 и pc из 0x4, а 0x2000 0000 и 0x0 не отображаются вместе после запуска .
Итак, у нас есть две догадки:
- Система не выполняет сопоставление от 0x2000 0000 до 0x0, но присваивает значения 0x2000 0000 и 0x20000004 SP и ПК при запуске с помощью внутреннего метода системы.
- Система выполняет сопоставление от 0x2000 0000 до 0x0 во время включения питания. После запуска (после включения MSP и ПК) сопоставление отключается, а затем два пространства открываются независимо.
Я не нашел никакой информации, чтобы объяснить это, но эффект, достигаемый обоими, одинаков.Лично я предпочитаю второй, который легко запомнить.
Вырежьте реальное изображение, и вы увидите, что они действительно разные.

3.2 Методика эксперимента
3.2.1 Создание нового элемента проекта RAM
Найдите простой проект, который может стабильно работать на флеш-памяти, и создайте новый элемент проекта для запуска RAM.
Значение установки этого элемента заключается в том, что измененная здесь конфигурация, глобальные макросы и т. д. не повлияют на конфигурацию флэш-памяти. Они независимы, и переключение очень удобно.
После переключения вы увидите, что название проекта слева другое.

За исключением связанных с конфигурацией, все добавленные файлы кода являются общим набором.
3.2.2 Изменение адресов ПЗУ и ОЗУ
Каждый должен заранее ознакомиться с настройкой загрузки флеш-памяти.
Здесь мы переключаемся на загрузку из ОЗУ.
Сначала посмотрите на размер скомпилированного файла.
Откройте файл карты
можно увидеть
Размер созданного bin-файла составляет 5884 байта.
Таким образом, мы можем выделить в ПЗУ более 5884.
Здесь тоже яма, это последнее слово.
3.2.3 настройки вкладки отладки

Удалить приложение загрузки при запуске
Загрузите CpuRam.ini, который я также нашел в Интернете.
3.2.4 Добавить глобальный макрос VECT_TAB_SRAM

VECT_TAB_SRAM в основном используется для сброса таблицы векторов прерываний во время systemInit.

3.2.5 Вкладка "Настроить утилиты"

3.2.6 Изменение уровня пина загрузки оборудования
Подключите Boot0 и BOOT1 к высокому уровню.
3.2.7 Запуск в режиме отладки
ОЗУ нельзя запрограммировать на загрузку флеш-памяти таким образом, и нельзя ее перезапустить после выключения питания.
в основном работает в режиме отладки.
После входа в отладку вы можете пошагово, на полной скорости и сбросить.
В Интернете есть сообщения о том, что они не могут сбросить настройки, но я с ними не сталкивался. Они могут работать нормально.
Иногда он будет нестабильным при запуске и выйдет из режима отладки при сообщении об ошибке, но его также можно использовать.
Я долго бегал после просмотра картинки.
4. Обнаружена яма
Когда я запускал ОЗУ, я вводил аппаратное исключение каждый раз, когда сталкивался с SystemInit, что меня очень расстраивало. Я чувствовал, что это ненормально, как только я нажимал на стек. Однако я был действительно подавлен, когда отслеживал изменения MSP в соответствии с моими ожиданиями. На выяснение причины ушло много времени.
Я видел этот абзац в китайском руководстве по stm32 раньше,
stm32f103, который я использовал для тестирования, я думал, что RAM 64k, то есть 0x2000 0000
0x20010000, поэтому ROM разделен на 0x2000 0000
0x2000 8000, RAM разделен на 0x2000 8000
0x 2001 0000 .
На самом деле это совсем не так. ОЗУ stm32f103c8t6 составляет всего 20 КБ, поэтому пара операций SP является ненормальной и осуществляется доступ к недопустимому адресу.
После изменения размера это нормально. 