ESP32 это микроконтроллер, основанный двух на ядрах Xtensa LX6 CPU с Гарвардской архитектурой (память инструкций и память данных физически разделены). Вся встроенная память, внешняя память и периферийные устройства расположены на шине данных и/или команд этих CPU.
Примечание: здесь приведен перевод раздела "System and Memory" технического руководства esp32_technical_reference_manual_en.pdf [1]. Незнакомые термины и сокращения см. в Словарике, в конце статьи.
С некоторыми небольшими исключениями (см. описание далее) карта памяти этих двух CPU симметрична, т. е. они используют одно и то же адресное пространство одной и той же памяти. Несколько периферийных устройств в системе могут обращаться к памяти через DMA [2]. В этом руководстве оба CPU условно именуются как PRO_CPU и APP_CPU (т. е. один предназначен для "протоколов", и другой для "приложения"), однако для большинства применений они равноправны и взаимозаменяемы.
Особенности адресации:
– Симметричное для двух CPU отображение на карту памяти блоков RAM и периферийных устройств. – 4 GB адресного пространства (разрядность адреса 32 бита) для обоих шин данных и инструкций. – 1296 KB адресов для встроенной памяти. – 19704 KB адресов для внешней памяти. – 512 KB адресов для периферийных устройств (всего имеется 41 периферийных устройств). – К некоторым регионам встроенной и внешней памяти можно получить доступ либо через шину данных, либо через шину инструкций. – 328 KB адресного пространства DMA (всего имеется 13 модулей DMA).
Внешняя память. Находящаяся вне кристалла последовательная память SPI может быть отображена на доступное адресное пространство как внешняя память. Части встроенной памяти могут использоваться как прозрачный кэш для этой внешней памяти:
– Поддерживается до 16 MB внешней SPI Flash. – Поддерживается до 8 MB внешней SPI SRAM.
На рис. 1 показана блок-схема структуры системы, блок-схема рис. 2 иллюстрирует структуру адресного пространства.
Рис. 1. Общая структура системы.
Рис. 2. Распределение адресного пространства.
[Карта памяти]
Каждый из двух Xtensa LX6 CPU Гарвардской архитектуры имеет 4 GB адресного пространства (32-разрядный адрес) address space. Адресные пространства симметричны между этими двумя CPU (т. е. оно общее).
Адреса ниже 0x40000000 обслуживаются через шину данных. Адреса в диапазоне 0x40000000 .. 0x4FFFFFFF обслуживаются с использованием шины инструкций. И наконец, адреса выше и включая 0x50000000 совместно используются шинами данных и инструкций.
И шина данных, и шина инструкций, обе используют принцип порядка байт little-endian [3]. Например, значения байтовых адресов 0, 1, 2, 3 соответственно обращаются к наименее значимому, второму наименее значимому, второму более значимому и самому значимому байту 32-разрядного слова, сохраненному по адресу 0 (т. е. чем больше адрес, тем более значимый байт слова). CPU может обращаться к шине данных через операции не выровненного байтового доступа, доступа к половине слова и к полному слову для операций чтение и запись. CPU может читать и записывать данные через шину инструкций, однако только через доступ к словам (по байтовому адресу, нацело делящемуся на 4). Не выровненный доступ через шину инструкций приведет к ошибке исключения (CPU exception).
Каждый CPU может напрямую обращаться к встроенной памяти как через шину данных, так и через шину инструкций, к внешней памяти, которая отображена на адресной пространство (через систему прозрачного кэширования и MMU), и к периферийным устройствам. Таблица 1 показывает диапазоны адресов, которые могут быть доступны через шину данных и шину инструкций каждого CPU.
Некоторые области встроенной памяти и некоторые области внешней памяти могут быть доступны через шину данных, или через шину инструкций. В этих случаях одна и та же паять доступна для любого CPU в двух диапазонах адресов.
Эта память состоит из 4 сегментов: internal ROM (448 KB), internal SRAM (520 KB), RTC FAST memory (8 KB) и RTC SLOW memory (8 KB).
448 KB internal ROM поделено на 2 части: Internal ROM 0 (384 KB) и Internal ROM 1 (64 KB). 520 KB internal SRAM поделено на 3 части: Internal SRAM 0 (192 KB), Internal SRAM 1 (128 KB) и Internal SRAM 2 (200 KB). Области RTC FAST Memory и RTC SLOW Memory обе реализованы как SRAM.
В таблице 2 перечислены встроенные области памяти и их диапазоны адресов на шинах данных и инструкций.
Таблица 2. Embedded Memory Address Mapping.
Шина
Диапазон адресов
Размер
Назначение
Комментарий
Младший адрес
Старший адрес
Данные
0x3FF80000
0x3FF81FFF
8 KB
RTC FAST Memory
Только PRO_CPU
0x3FF82000
0x3FF8FFFF
56 KB
Зарезервировано
-
Данные
0x3FF90000
0x3FF9FFFF
64 KB
Internal ROM 1
-
0x3FFA0000
0x3FFADFFF
56 KB
Зарезервировано
-
Данные
0x3FFAE000
0x3FFDFFFF
200 KB
Internal SRAM 2
DMA
0x3FFE0000
0x3FFFFFFF
128 KB
Internal SRAM 1
Инструкции
0x40000000
0x40007FFF
32 KB
Internal ROM 0
Remap
0x40008000
0x4005FFFF
352 KB
-
0x40060000
0x4006FFFF
64 KB
Зарезервировано
-
Инструкции
0x40070000
0x4007FFFF
64 KB
Internal SRAM 0
Кэш
0x40080000
0x4009FFFF
128 KB
-
0x400A0000
0x400AFFFF
64 KB
Internal SRAM 1
-
0x400B0000
0x400B7FFF
32 KB
Remap
0x400B8000
0x400BFFFF
32 KB
-
0x400C0000
0x400C1FFF
8 KB
RTC FAST Memory
Только PRO_CPU
Данные/инструкции
0x50000000
0x50001FFF
8 KB
RTC SLOW Memory
-
Internal ROM 0. Емкость Internal ROM 0 составляет 384 KB. Она доступна для обоих CPU через диапазон адресов 0x40000000 .. 0x4005FFFF, которые находятся на шине инструкций.
Диапазон адресов первых 32 KB ROM 0 (0x40000000 .. 0x40007FFF) могут быть перенаправлены (remap), чтобы получить доступ к части Internal SRAM 1, которая нормально находится в диапазоне адресов 0x400B0000 .. 0x400B7FFF. При переназначении 32 KB SRAM больше не будут доступны через диапазон адресов 0x400B0000 .. 0x400B7FFF, однако эти 32 KB SRAM все еще будут доступны через шину данных (0x3FFE8000 .. 0x3FFEFFFF). Это можно делать на каждом CPU: установка бита 0 регистра DPORT_PRO_BOOT_REMAP_CTRL_REG или DPORT_APP_BOOT_REMAP_CTRL_REG будет перенаправлять (remap) SRAM для PRO_CPU и APP_CPU соответственно.
Internal ROM 1. Емкость Internal ROM 1 составляет 64 KB. Его можно прочитать любым CPU в адресном диапазоне 0x3FF90000 .. 0x3FF9FFFF шины данных.
Internal SRAM 0. Емкость Internal SRAM 0 составляет 192 KB. Аппаратура может быть сконфигурирована для использования первых 64 KB для кэша доступа к внешней памяти. Когда первые 64 KB не используются как кэш, их можно читать и записывать любым CPU по адресам 0x40070000 .. 0x4007FFFF шины инструкций. Остальные 128 KB можно всегда читать и записывать любым CPU по адресам 0x40080000 .. 0x4009FFFF шины инструкций.
Internal SRAM 1. Емкость Internal SRAM 1 составляет 128 KB. Любой CPU может читать и записывать эту память по адресам 0x3FFE0000 .. 0x3FFFFFFF шины данных, и также по адресам 0x400A0000 .. 0x400B_FFFF шины инструкций.
Диапазон адресов, доступ к которому осуществляется через шину инструкций в обратном порядке (по словам) по сравнению с доступом через шину данных. То есть, обращение по адресам:
0x3FFE0000 и 0x400BFFFC осуществляется к одному и тому же слову 0x3FFE0004 и 0x400BFFF8 осуществляется к одному и тому же слову 0x3FFE0008 и 0x400BFFF4 осуществляется к одному и тому же слову ... 0x3FFFFFF4 и 0x400A0008 осуществляется к одному и тому же слову 0x3FFFFFF8 и 0x400A0004 осуществляется к одному и тому же слову 0x3FFFFFFC и 0x400A0000 осуществляется к одному и тому же слову.
Шина данных и шина инструкций все еще обе little-endian, так что порядок байт отдельных слов не становится обратным между адресными пространствами. Например, байтовый доступ по адресу:
0x3FFE0000 дает доступ к самому младшему значащему байту слова, доступного по адресу 0x400BFFFC. 0x3FFE0001 дает доступ к следующему по старшинству байту слова, доступного по адресу 0x400BFFFC. 0x3FFE0002 дает доступ к следующему по старшинству байту слова, доступного по адресу 0x400BFFFC. 0x3FFE0003 дает доступ к самому старшему значащему байту слова, доступного по адресу 0x400BFFFC. 0x3FFE0004 дает доступ к самому младшему значащему байту слова, доступного по адресу 0x400BFFF8. 0x3FFE0005 дает доступ к следующему по старшинству байту слова, доступного по адресу 0x400BFFF8. 0x3FFE0006 дает доступ к следующему по старшинству байту слова, доступного по адресу 0x400BFFF8. 0x3FFE0007 дает доступ к самому старшему значащему байту слова, доступного по адресу 0x400BFFF8. ... 0x3FFFFFF8 дает доступ к самому младшему значащему байту слова, доступного по адресу 0x400A0004. 0x3FFFFFF9 дает доступ к следующему по старшинству байту слова, доступного по адресу 0x400A0004. 0x3FFFFFFA дает доступ к следующему по старшинству байту слова, доступного по адресу 0x400A0004. 0x3FFFFFFB дает доступ к самому старшему значащему байту слова, доступного по адресу 0x400A0004. 0x3FFFFFFC дает доступ к самому младшему значащему байту слова, доступного по адресу 0x400A0000. 0x3FFFFFFD дает доступ к следующему по старшинству байту слова, доступного по адресу 0x400A0000. 0x3FFFFFFE дает доступ к следующему по старшинству байту слова, доступного по адресу 0x400A0000. 0x3FFFFFFF дает доступ к самому старшему значащему байту слова, доступного по адресу 0x400A0000.
Часть этой памяти может быть перенаправлена (remap) на адресное пространство ROM 0, см. "Internal Rom 0" для дополнительной информации.
Internal SRAM 2. Емкость Internal SRAM 2 составляет 200 KB. Она может быть прочитана и записана любым CPU по адресам 0x3FFAE000 .. 0x3FFDFFFF шины данных.
DMA. DMA использует ту же самую схему адресации, что и шина данных CPU для чтения и записи Internal SRAM 1 и Internal SRAM 2. Это значит, что DMA использует диапазон адресов 0x3FFE0000 .. 0x3FFFFFFF для чтения и записи Internal SRAM 1, и диапазон адресов 0x3FFAE000 .. 0x3FFD_FFFF для чтения и записи Internal SRAM 2.
В ESP32 блоками DMA оборудованы 13 периферийных устройств, в таблице 3 перечислены эти устройства.
Таблица 3. Периферийные устройства с модулями DMA.
UART0
UART1
UART2
SPI1
SPI2
SPI3
I2S0
I2S1
SDIO Slave
SDMMC
EMAC
Bluetooth
Wi-Fi
RTC FAST Memory. RTC FAST Memory занимает 8 KB SRAM. Она может быть прочитана и записана только ядром PRO_CPU через диапазон адресов 0x3FF80000 .. 0x3FF81FFF шины данных, или через диапазон адресов 0x400C0000 .. 0x400C1FFF шины инструкций. В отличие от большинства других областей памяти, к памяти RTC FAST нельзя получить доступ из ядра APP_CPU.
Два диапазона адресов доступа PRO_CPU к памяти RTC FAST имеют одинаковый порядок. Так, например, адреса 0x3FF80000 и 0x400C0000 обращаются к одному и тому же слову. На APP_CPU эти адреса не предоставляют доступ к RTC FAST Memory или к любой другой области памяти.
RTC SLOW Memory. RTC SLOW Memory занимает 8 KB SRAM, и эта область может быть прочитана и записана любым CPU в диапазоне адресов 0x50000000 .. 0x50001FFF. Этот диапазон адресов одинаковый и для шины данных, и для шины инструкций.
ESP32 может получить доступ к внешней памяти SPI Flash и SPI SRAM в качестве внешней памяти. Таблица 4 предоставляет список областей внешней памяти, к которым может получить доступ любой CPU через шину данных и шину инструкций. Когда CPU осуществляет доступ к внешней памяти через кэш и MMU, кэш будет отображать адрес CPU на внешний физический адрес памяти (адресном пространстве внешней памяти), в соответствии с настройками MMU. С помощью этого отображения адресов ESP32 может адресовать 16 MB External Flash и 8 MB External SRAM.
Таблица 4. External Memory Address Mapping.
Шина
Диапазон адресов
Размер
Назначение
Комментарий
Младший адрес
Старший адрес
Данные
0x3F400000
0x3F7FFFFF
4 MB
External Flash
Чтение
0x3F800000
0x3FBFFFFF
4 MB
External SRAM
Чтение и запись
Инструкции
0x400C2000
0x40BFFFFF
11512 KB
External Flash
Чтение
Кэш. Как показано на рис. 3, каждый из двух CPU имеет 32 KB кэша для доступа к внешней памяти. PRO_CPU использует бит PRO_CACHE_ENABLE в регистре DPORT_PRO_CACHE_CTRL_REG, чтобы разрешить кэш, в то время как APP_CPU использует бит APP_CACHE_ENABLE в регистре DPORT_APP_CACHE_CTRL_REG для разрешения той же самой функции.
Рис. 3. Блок-схема кэша.
ESP32 использует двусторонний ассоциативный кэш (two-way set-associative cache). Когда функция кэша используется либо PRO_CPU, либо APP_CPU, биты CACHE_MUX_MODE[1:0] в регистре DPORT_CACHE_MUX_MODE_REG можно установить для выбора POOL0 или POOL1 в памяти Internal SRAM0 для использования в качестве кэша. Когда оба PRO_CPU и APP_CPU используют функцию кэширования, POOL0 и POOL1 в памяти Internal SRAM0 будут использоваться одновременно в качестве кэша, хотя они также могут использоваться шиной инструкций. Это показано ниже в таблице 5.
Таблица 5. Режим кэша памяти.
CACHE_MUX_MODE
POOL0
POOL1
0
PRO_CPU
APP_CPU
1
PRO_CPU/APP_CPU
-
2
-
PRO_CPU/APP_CPU
3
APP_CPU
PRO_CPU
Как показано в таблице 5, когда биты CACHE_MUX_MODE установлены в 1 или 2, PRO_CPU и APP_CPU не могут разрешить функцию кэша одновременно. Когда функция кэша разрешена, POOL0 или POOL1 могут использоваться только в качестве памяти кэша, и не могут также использоваться шиной инструкций.
Кэш ESP32 поддерживает функцию Flush. Когда используется Flush, то данные, которые записаны в кэше, перезаписываются в External SRAM, и становятся в кэше не актуальными. Чтобы разрешить функцию Flush, сначала очистите бит x_CACHE_FLUSH_ENA в регистре DPORT_x_CACHE_CTRL_REG, затем установите этот бит в 1. После этого аппаратура системы установит в 1 бит x_CACHE_FLUSH_DONE. Здесь буквой x обозначено "PRO" или "APP", показывая принадлежность операции flush к определенному ядру CPU.
Для дополнительной информации по адресации кэша ESP32 см. врезки "Внутренняя память" и "Внешняя память".
Скорость памяти. Память ROM, как и память SRAM, обе тактируются от CPU_CLK, и к ним CPU может получить доступ за один такт. Память RTC FAST тактируется от APB_CLOCK, и память RTC SLOW тактируется от FAST_CLOCK, так что доступ к этим двум областям памяти может быть медленнее. Для доступа к памяти DMA использует APB_CLK.
Внутри SRAM организована в виде банков по 32K. Каждый CPU и канал DMA может одновременно обращаться к SRAM на полной скорости при условии, что они имеют доступ к адресам в различных банках памяти.
[Периферийные устройства]
У ESP32 есть 41 периферийных устройства. В таблице 6 показаны эти устройства и их соответствующие диапазоны адресов. Почти все модули периферийных устройств могут быть доступны для любого CPU по одному и тому же адресу за только одним исключением: PID-контроллер.
Таблица 6. Peripheral Address Mapping.
Шина
Диапазон адресов
Размер
Назначение
Комментарий
Младший адрес
Старший адрес
Данные
0x3FF00000
0x3FF00FFF
4 KB
Регистр DPort
0x3FF01000
0x3FF01FFF
4 KB
Ускоритель AES
0x3FF02000
0x3FF02FFF
4 KB
Ускоритель RSA
0x3FF03000
0x3FF03FFF
4 KB
Ускоритель SHA
0x3FF04000
0x3FF04FFF
4 KB
Secure Boot
0x3FF05000
0x3FF0FFFF
44 KB
Зарезервировано
Данные
0x3FF10000
0x3FF13FFF
16 KB
Таблица кэша MMU
0x3FF14000
0x3FF1EFFF
44 KB
Зарезервировано
Данные
0x3FF1F000
0x3FF1FFFF
4 KB
PID-контроллер
Периферийное устройство привязано к CPU
0x3FF20000
0x3FF3FFFF
128 KB
Зарезервировано
Данные
0x3FF40000
0x3FF40FFF
4 KB
UART0
0x3FF41000
0x3FF41FFF
4 KB
Зарезервировано
Данные
0x3FF42000
0x3FF42FFF
4 KB
SPI1
0x3FF43000
0x3FF43FFF
4 KB
SPI0
0x3FF44000
0x3FF44FFF
4 KB
GPIO
0x3FF45000
0x3FF47FFF
12 KB
Зарезервировано
Данные
0x3FF48000
0x3FF48FFF
4 KB
RTC
0x3FF49000
0x3FF49FFF
4 KB
IO MUX
0x3FF4A000
0x3FF4AFFF
4 KB
Зарезервировано
Данные
0x3FF4B000
0x3FF4BFFF
4 KB
SDIO Slave
Одна из 3 областей памяти
0x3FF4C000
0x3FF4CFFF
4 KB
UDMA1
0x3FF4D000
0x3FF4EFFF
8 KB
Зарезервировано
Данные
0x3FF4F000
0x3FF4FFFF
4 KB
I2S0
0x3FF50000
0x3FF50FFF
4 KB
UART1
0x3FF51000
0x3FF52FFF
8 KB
Зарезервировано
Данные
0x3FF53000
0x3FF53FFF
4 KB
I2C0
0x3FF54000
0x3FF54FFF
4 KB
UDMA0
0x3FF55000
0x3FF55FFF
4 KB
SDIO Slave
Одна из 3 областей памяти
0x3FF56000
0x3FF56FFF
4 KB
RMT
0x3FF57000
0x3FF57FFF
4 KB
PCNT
0x3FF58000
0x3FF58FFF
4 KB
SDIO Slave
Одна из 3 областей памяти
0x3FF59000
0x3FF59FFF
4 KB
LED PWM
0x3FF5A000
0x3FF5AFFF
4 KB
Контроллер eFuse
0x3FF5B000
0x3FF5BFFF
4 KB
Шифрование Flash
0x3FF5C000
0x3FF5DFFF
8 KB
Зарезервировано
Данные
0x3FF5E000
0x3FF5EFFF
4 KB
MCPWM0
0x3FF5F000
0x3FF5FFFF
4 KB
TIMG0
0x3FF60000
0x3FF60FFF
4 KB
TIMG1
0x3FF61000
0x3FF63FFF
12 KB
Зарезервировано
Данные
0x3FF64000
0x3FF64FFF
4 KB
SPI2
0x3FF65000
0x3FF65FFF
4 KB
SPI3
0x3FF66000
0x3FF66FFF
4 KB
SYSCON
0x3FF67000
0x3FF67FFF
4 KB
I2C1
0x3FF68000
0x3FF68FFF
4 KB
SDMMC
0x3FF69000
0x3FF6AFFF
8 KB
EMAC
0x3FF6B000
0x3FF6BFFF
4 KB
Зарезервировано
Данные
0x3FF6C000
0x3FF6CFFF
4 KB
MCPWM1
0x3FF6D000
0x3FF6DFFF
4 KB
I2S1
0x3FF6E000
0x3FF6EFFF
4 KB
UART2
0x3FF6F000
0x3FF6FFFF
4 KB
Зарезервировано
0x3FF70000
0x3FF70FFF
4 KB
Зарезервировано
0x3FF71000
0x3FF74FFF
16 KB
Зарезервировано
Данные
0x3FF75000
0x3FF75FFF
4 KB
RNG
0x3FF76000
0x3FF7FFFF
40 KB
Зарезервировано
Замечания:
• Периферийные устройства, к которым CPU осуществляет доступ через адреса 0x3FF40000 .. 0x3FF7FFFF (DPORT адрес), также могут быть доступны через адреса 0x60000000 ~ 0x6003FFFF (AHB адрес). Адрес (0x3FF40000 + n) и (0x60000000 + n) производят доступ к одному и тому же содержимому, где n = 0 .. 0x3FFFF. • CPU может обратиться к периферийным устройствам через адрес DPORT более эффективно, чем через адрес AHB. Однако адрес DPORT адрес характеризуется спекулятивными чтениями, это означает, что не гарантируется, что каждое чтение достоверно. Дополнительно адрес DPORT нарушит порядок доступа операций чтения/записи на шине, чтобы повысить производительность, что может привести к аварийному сбою программ, у которых есть строгие требования к порядку доступа чтения/записи. С другой стороны использование адреса AHB для чтения регистров FIFO будет приводить к непредсказуемым ошибкам. Чтобы обойти эти проблемы, строго следуйте инструкциям, задокументированным в документе [4], особенно в секциях 3.3, 3.10, 3.16 и 3.17.
Асимметричный PID-контроллер. В системе ESP32 есть два PID-контроллера. Они обслуживают соответственно ядра PRO_CPU и APP_CPU. PRO_CPU и APP_CPU могут получить доступ только к своему PID-контроллеру, но не к чужому. Каждый CPU использует одинаковый диапазон памяти 0x3FF1F000 .. 3FF1FFFF для доступа к своему PID-контроллеру.
Несмежные (прерывистые) диапазоны адресов периферийных устройств. Периферийное устройство SDIO Slave состоит из трех частей, и два CPU используют несмежные адреса для доступа к ним. Три части доступны в диапазонах адресов 0x3FF4B000 .. 3FF4BFFF, 0x3FF55000 .. 3FF55FFF и 0x3FF58000 .. 3FF58FFF шины данных каждого CPU. Подобно другим периферийным устройствам, доступ к этим периферийным устройствам идентичен для обоих CPU.