Программирование ARM ESP32: SPI Flash API Tue, March 05 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

ESP32: SPI Flash API Печать
Добавил(а) microsin   

Компонент spi_flash содержит API-функции для чтения, записи, стирания и отображения на адресное пространство (memory mapping) данных, находящихся во внешней памяти SPI flash. Компонент spi_flash также содержит высокоуровневые API-функции, которые работают с разделами, определенными в таблице разделов [2].

Существует отличие API для версий ESP-IDF до v4.0, функционал API-функций esp_flash_* не ограничивается "основной" микросхемой SPI flash (микросхема SPI flash, с которой запускается программа). С указателями на разные микросхемы можно получить доступ к их содержимому, не только к SPI0/SPI1, но также и к другим шинам SPI наподобие SPI2.

Замечания:

• Вместо доступа через кэш к подключенному перириферийному устройству SPI0, большинство esp_flash_* API передают данные через другие периферийные устройства SPI наподобие SPI1, SPI2, и т. д. Это позволяет получить доступ не только к основной flash, но также и к внешней SPI flash.
• Однако из-за ограничений кэша операции через него ограничены основной памятью flash (main flash). Ограничение на диапазон адресов для этих операций также накладывается со стороны кэша. Кэш не может получить доступ к внешним микросхемам flash или к адресному пространству свыше его возможностей. Эти операции кэша включают: отображение на карту памяти (mmap), чтение/запись с поддержкой шифрования (encrypted read/write), выполнение кода или доступ к переменным из flash.
• Flash API после ESP-IDF v4.0 больше не является атомарным. Если операция записи происходит во время другой выполняющейся операции чтения, и для обоих операций перекрываются адреса, то данные, которые вернет операция чтения, могут содержать как старые, так и новые данные (которые были обновлены операцией записи).

Kconfig-опция CONFIG_SPI_FLASH_USE_LEGACY_IMPL может использоваться для переключения функций spi_flash_* обратно в реализацию до ESP-IDF v4.0. Однако в этом случае размер кода может быть больше, если одновременно используется новый и старый API.

Чтение и запись с шифрованием используют старую реализацию, даже если не разрешена опция CONFIG_SPI_FLASH_USE_LEGACY_IMPL. Так что шифрованные операции с flash поддерживаются только для основной микросхемы flash (но не с другими микросхемами flash, т. е. на SPI1 с другими сигналами выборки CS, или на других шинах SPI). Чтение через кэш поддерживается только на основной памяти flash, которая определяется аппаратно.

[Поддержка особенностей микросхем flash]

Микросхемы с режимами Quad/Dual. Функции разных микросхем flash реализуются разными способами, что требует специальной поддержки. Быстрое/медленное чтение (fast/slow read) и двойной режим (Dual mode, DOUT/DIO) почти всех микросхем с 24-битным адресом, потому что они не требуют любых специфичных, зависящих от производителя команд.

Счетверенный режим (Quad mode, QIO/QOUT) поддерживается для микросхем следующих типов:

ISSI
GD
MXIC
FM
Winbond
XMC
BOYA

Опциональные функции. Существуют некоторые функции, которые поддерживаются не всеми микросхемами flash, или не поддерживаются всеми микросхемами Espressif. Эти функции включают:

• flash с 32-битным адресом - обычно это значит, что у микросхемы повышенная емкость (равная или больше чем 16 MB), которая требует больших адресов.
• Flash unique ID - означает, что flash поддерживает уникальный 64-битный идентификатор.

Если Вы хотите использовать такие функции, то убедитесь, что и ESP32, и все микросхемы flash в Вашем изделии поддерживают эти функции. Более подробную информацию см. документации [3].

Также Вы можете переписать драйвер для своей микросхемы flash, см. [4].

[Инициализация устройства flash]

Чтобы использовать esp_flash_* APIs, Вам нужно инициализировать микросхему flash на определенной шине certain SPI, как показано ниже:

1. Вызовите spi_bus_initialize() для правильной инициализации шины шины SPI. Эта функция инициализирует ресурсы (I/O, DMA, прерывания), совместно используемые этой шиной.
2. Вызовите spi_bus_add_flash_device() для подключения устройства flash к этой шине. Эта функция выделяет память и заполняет поля структуры esp_flash_t. Здесь также инициализируется порт ножки выборки (CS I/O).
3. Вызовите esp_flash_init() для запуска реального обмена с микросхемой. Этот вызов также определит тип микросхемы, и повлияет на последующие операции.

Примечание: в настоящее время к одной шине может быть подключено несколько микросхем.

[SPI Flash Access API]

Для работы с данными на микросхеме flash существует набор API-функций:

esp_flash_read() считывает данные и помещает из в RAM.
esp_flash_write() записывает данные из RAM.
esp_flash_erase_region() стирает указанный регион памяти flash.
esp_flash_erase_chip() полностью стирает всю микросхему flash.
esp_flash_get_chip_size() возвратит размер микросхемы flash в байтах, как это было сконфигурировано в menuconfig.

Старайтесь как правило избегать использования функций для "сырого" физического доступа через SPI к основной микросхеме SPI flash, преимущественно применяйте функции, работающие с разделами (см. далее "API таблицы разделов").

[Размер SPI Flash]

Размер SPI flash конфигурируется путем записи поля в заголовке образа программного загрузчика, прошиваемого со смещением 0x1000.

По умолчанию размер SPI flash детектируется утилитой esptool.py, когда загрузчик второй стадии [5] записывается во flash, и заголовок обновляется корректным размером flash. Альтернативно можно сгенерировать размер фиксированным путем установки CONFIG_ESPTOOLPY_FLASHSIZE в конфигурации проекта.

Если необходимо отменить сконфигурированный размер flash во время работы кода (runtime), то можно установить поле chip_size структуры g_rom_flashchip. Этот размер используют функции esp_flash_* (как в коде приложения и загрузчика, так и в коде ROM) для проверки границ адресов.

[Ограничения по конкурентному доступу для flash на шине SPI1]

Важное замечание: шина SPI0/1 совместно используется кэшем инструкций и данных (для выполнения кода firmware) и периферийным устройством SPI1 (управляется драйверами, включая этот драйвер SPI flash). Следовательно, вызов SPI Flash API на шине SPI1 (включая main flash) значительно повлияет на всю систему, подробности см. в следующей врезке.

Операции на шине SPI1 включают вызов SPI Flash API или других драйверов шины SPI1, любые операции наподобие read/write/erase, либо другие определяемые пользователем операции SPI, независимо от основной памяти flash или от других подчиненных устройств SPI.

На ESP32 кеширование шин SPI0/1 должно быть запрещено во время операций read/write/erase.

Когда кэши запрещены. В таких условиях все ядра CPU всегда выполняют код из RAM и осуществляют доступ только к данным во внутреннем ОЗУ (IRAM). API-вызовы для запрета кэшей будут сделаны автоматически и прозрачно.

Способ, которым эти API-вызовы запрещают кэш, будет приостанавливать все другие задачи. Кроме того, все прерывания, не связанные с IRAM, будут запрещены. Другое ядро будет ждать завершения операций с flash в цикле опроса занятости (busy loop).

Также см. далее "Функции операционной системы" и врезку "Блокировка шины SPI".

Подобных ограничений нет на других шинах SPI, отличающихся от SPI0/SPI1.

Для получения информации по отличиям внутреннего ОЗУ (например IRAM, DRAM) и кэша flash см. документацию по типам памяти [7].

IRAM-Safe ISR. Для обработчиков прерываний (ISR), которые должны выполняться, когда кэш запрещен (например для операций с низкой латентностью), установите флаг ESP_INTR_FLAG_IRAM при регистрации таких ISR.

Вы должны гарантировать, что все данные и функции, к которым осуществляют доступ эти ISR, включая те, которые вызывают обработчики, размещены в IRAM или в DRAM. См. "How to place code in IRAM" в статье [7].

Если функция или символ в настоящее время не размещен корректно в IRAM/DRAM, и ISR делает чтение из кэша flash во время операции с flash, то произойдет общий сбой из-за исключения недопустимой инструкции Illegal Instruction exception (для кода, который должен находиться в IRAM), или будут прочитаны мусорные данные (для данных константы, которые должны находиться в DRAM).

Замечание: при работе в ISR со строками не рекомендуется использовать printf и другие функции вывода. Для целей отладки используйте ESP_DRAM_LOGE() и другие подобные макросы, когда необходим вывод в лог из ISR. Убедитесь для этого случая, что и TAG, и строка форматирования размещены в DRAM.

Non-IRAM-Safe ISR. Если при регистрации ISR не установлен флаг ESP_INTR_FLAG_IRAM, то ISR не будет выполнен, когда кеширование отключено. Как только работа кэша восстановится, non-IRAM-safe прерывания будут снова разрешены. После этого момента ISR снова запустится как обычно. Это значит, что пока кэши запрещены, пользователи не увидят соответствующее аппаратное событие.

Для реализации мультиплексирования различных устройств от разных драйверов (SPI Master, SPI Flash, и т. д.) применяется блокировка SPI (bus lock) на каждой шине SPI. Драйверы могут присоединить свои драйверы к шине с арбитражем блокировки.

Каждая блокировка шины инициализируется в фоне зарегистрированной службой (BG), и все устройства, запрашивающие выполнение транзакции на шине, должны ожидать момента успешного завершения фоновой блокировки.

• Для шины SPI1 такой BG-блокировкой будет кэш, блокировка шины поможет запретить кеширование перед запуском работы устройства, и снова разрешить кеширование после того, как устройство освободит блокировку. Использование ISR не позволяет использовать устройства на SPI1 (нет смысла для задачи уступать свое процессорное время для других задач, когда кэш запрещен).

Существует довольно много ограничений при использовании драйвера мастера SPI Master на шине SPI1, см. "Notes on Using the SPI Master driver on SPI1 Bus" [8].

• Для других шин драйвер может зарегистрировать свой собственный ISR как BG. Блокировка шины заблокирует задачу устройства, когда она запрашивает исключительный доступ к шине, попытается запретить ISR, и разблокирует задачу устройства, позволяя ей эксклюзивно использовать шину, когда ISR был успешно запрещен. Затем задача освобождает блокировку, блокировка будет также пытаться возобновить работу ISR, если в ISR остались транзакции, ожидающие своего завершения.

[API таблицы разделов]

Проекты ESP-IDF используют таблицу разделов, чтобы обслуживать информацию по содержимому различных регионов памяти SPI flash memory (bootloader, различные бинарники приложений, данные, файловые системы). Дополнительную информацию по таблице разделов см. в документации [2].

Этот компонент предоставляет API-функции для просмотра информации по разделам, которые находятся в таблице разделов, и для выполнения операций с разделами. Эти функции декларированы в заголовочном файле esp_partition.h:

esp_partition_find() проверяет таблицу разделов на наличие в ней записей определенного типа, возвращая непрозрачный итератор по таблице.
esp_partition_get() возвращает структуру, описывающую раздел с указанным итератором.
esp_partition_next() смещает итератор на следующий найденный раздел.
esp_partition_iterator_release() освободит итератор, который был возвращен вызовом esp_partition_find.
esp_partition_find_first() - функция удобства, которая возвращает структуру, описывающую первый раздел, который нашел вызов esp_partition_find.
esp_partition_read(), esp_partition_write(), esp_partition_erase_range() эквивалентны функциям spi_flash_read(), spi_flash_write(), spi_flash_erase_range(), однако отличаются тем, что работают в пределах раздела.

Замечание: код приложения должен в большинстве случаев использовать именно API-функции esp_partition_* вместо низкоуровневых API-функций level esp_flash_*. API-функции таблицы разделов делают проверку границ и вычисляют корректные смещения по памяти flash, основываясь на данных, содержащихся в таблице разделов.

[SPI Flash Encryption]

Существует возможность зашифровать содержимое SPI flash, и оно будет прозрачно расшифровываться аппаратурой. Подробности см. в документации [9].

[Memory Mapping API]

У ESP32 есть функция аппаратного отображения регионов памяти flash на адресные пространства инструкций и данных. Это отображение работает только для операций чтения. Нельзя поменять содержимое памяти flash путем записи в отображенный регион памяти. Отображение происходит страницами по 64 KB. Подробную и информацию и существующие ограничения этой технологии см. в техническом руководстве по используемому процессору.

Обратите внимание, что некоторые страницы используются для отображения самого приложения, поэтому реальное количество доступных для отображения страниц может быть меньше, чем может обеспечить аппаратура.

Чтение данных из flash с использованием отображенного региона памяти - единственный способ расшифровать содержимое flash, когда разрешено шифрование (flash encryption). Расшифровка происходит прозрачно на уровне аппаратуры.

API-функции отображения памяти декларированы в заголовочных файлах esp_spi_flash.h и esp_partition.h:

spi_flash_mmap() отобразит регион физических адресов flash на область инструкций или данных CPU.
spi_flash_munmap() отменит ранее отображенный регион.
esp_partition_mmap() отобразит часть раздела на область инструкций или данных CPU.

Различия между spi_flash_mmap() и esp_partition_mmap() следующие:

• spi_flash_mmap() должна использовать физические адреса, выровненные на 64 KB.
• esp_partition_mmap() может использовать произвольные смещения в пределах раздела. Эта функция при необходимости подстраивает возвращаемый указатель на отображенную память.

Обратите внимание, что поскольку отображение памяти происходит страницами, то для esp_partition_mmap может произойти чтение данных вне раздела, независимо от расположения границ раздела.

Замечание: отображение поддерживается кэшем, поэтому отображение можно использовать только на основной памяти flash.

[Реализация SPI Flash]

Структура esp_flash_t хранит данные микросхем, а также 3 основные части этого API:

1. Драйвер хоста (host driver), который предоставляет аппаратную поддержку доступа к микросхеме.
2. Драйвер микросхемы (chip driver), который обеспечивает службу совместимости для различных микросхем.
3. Функции операционной системы (такие как например блокировка, задержка) на различных стадиях выполнения кода (первая, вторая стадия загрузки, или приложение).

Host driver. Драйвер хоста использует интерфейс (spi_flash_host_driver_t), определенный в заголовке spi_flash_types.h (находится в папке components\hal\include\hal). Этот интерфейс предоставляет некоторые общие функции для обмена с микросхемой.

В других файлах SPI HAL некоторые из этих функций реализованы с существующим функционалом ESP32 memory-spi. Однако из-за ограничений по скорости ESP32, слой HAL не может предоставить высокоскоростные реализации некоторых команд чтения (поэтому поддержка для этого была удалена). Файлы исходного кода драйвера хоста memspi_host_driver.h и memspi_host_driver.c реализуют высокоскоростную версию этих команд с функцией common_command, предоставленной в HAL, и создает обертку для этих функций как spi_flash_host_driver_t для использования на верхнем уровне.

Также Вы можете реализовать свой собственный драйвер хоста, даже через GPIO. Пока реализованы все функции в spi_flash_host_driver_t, функции esp_flash API могут получить доступ к flash независимо от оборудования на нижнем уровне.

Chip Driver. Драйвер микросхемы, определенный в заголовочном файле spi_flash_chip_driver.h (находится в папке components\spi_flash\include), делает обертку базовых функций, определенных драйвером хоста, для использования на уровне API.

Для некоторых операций необходимо, чтобы сначала были отправлены некоторые команды, или впоследствии было считано некоторое состояние. Некоторым микросхемам нужны разные команды или значения, либо требуется применить специальные способы реализации обмена.

Существует тип микросхем, который называется generic chip, он обозначает обычные микросхемы памяти. Другие драйверы для специальных микросхем могут быть определены на основе драйвера generic chip.

Драйвер микросхемы использует драйвер хоста.

Функции операционной системы. В настоящее время слой функций операционной системы предоставляет функции блокировки и задержки.

Блокировка, lock (см. выше врезку "Блокировка шины SPI") используется для разрешения конфликтов доступа к устройствам, подключенным к одной и той же шине SPI, и для доступа к микросхеме SPI Flash. Например:

1. На шине SPI1 должен быть запрещен кэш (используемый для захвата данных data/code в Flash и PSRAM), когда происходит доступ к микросхеме flash на шине SPI0/1.
2. На других шинах драйверу flash во избежание конфликтов нужно запретить ISR, зарегистрированный драйвером мастера шины SPI (SPI Master driver).
3. Некоторым устройствам драйвера SPI Master может потребоваться монопольное использование шины во время определенного периода времени (особенно когда в устройстве памяти нет сигнала выборки CS, либо этот сигнал управляется программно, как сделано в драйвере SDSPI).

Задержка используется некоторыми длительными операциями, которые требуют от мастера ожидания или периодического опроса.

API верхнего уровня оборачивает эти функции драйвера и операционной системы в единый компонент, который также предоставляет некоторую проверку аргументов функций.

Функции операционной системы также помогают избежать срабатывания сторожевого таймера (watchdog timeout) во время стирания больших областей flash. В течение этого времени CPU занят задачей стирания flash. Этот процесс останавливает выполнение других задач. К этим задачам относится также задача ожидания FreeRTOS (idle task), которая сбрасывает сторожевой таймер (watchdog timer, WDT). Если выбрана опция конфигурации CONFIG_ESP_TASK_WDT_PANIC, и операция с памятью flash происходит по времени дольше, чем таймаут сторожевого таймера, то произойдет (нежелательная) перезагрузка системы.

Довольно трудно полностью устранить риск возникновения такого события, потому что время стирания меняется в зависимости от используемых микросхем драйвера, что затрудняет обеспечение совместимости для драйверов flash. Таким образом, пользователям нужно уделить этому моменту особое внимание, рекомендуется следующее:

1. Разрешить опцию CONFIG_SPI_FLASH_YIELD_DURING_ERASE, чтобы планировщик мог восстанавливать переключение задач во время стирания памяти flash. Кроме того, могут использоваться следующие параметры.

• Увеличение CONFIG_SPI_FLASH_ERASE_YIELD_TICKS или CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS в menuconfig.
• Вы также можете увеличить CONFIG_ESP_TASK_WDT_TIMEOUT_S в menuconfig для увеличения периода таймаута сторожевого таймера. Однако при этом ранее отслеживаемые таймауты могут больше не определяться.

2. Помните о последствиях разрешения опции CONFIG_ESP_TASK_WDT_PANIC при выполнении длительных операций с памятью SPI flash, которые приведут к срабатыванию таймаута. Однако эта опция может также помочь решить проблему возникновения неожиданных исключений (unexpected exceptions), т. е. ошибок в Вашем приложении. Необходимо принять обдуманное решение для реальной рабочей ситуации.

3. Во время разработки своих проектов внимательно изучите фактическую работу памяти flash в соответствии с требуемыми и ограничениями по времени стирания. Всегда допускайте разумное резервирование в зависимости от специфических требований для изделия, когда конфигурируете порог таймаута стирания flash, что позволяет повысить надежность конечной продукции и отсутствие заметных зависаний.

[Технические подробности реализации]

Для выполнения некоторых операций с памятью flash необходимо убедиться, что оба ядра CPU не выполняют любой код из flash во время операции с flash:

- В одноядерной системе SDK должен запретить прерывания или планировщик перед выполнением операции с flash.
- В двуядерной системе SDK должен убедиться, что оба ядра CPU не выполняют какой-либо код из flash.

Когда API-функция SPI flash вызывается на CPU A (это может быть ядро PRO или APP), запускается функция spi_flash_op_block_func на CPU B с использованием esp_ipc_call API. Это API выводит из сна высокоприоритетную задачу на CPU B, и указывает выполнить функцию, для этого случая это функция spi_flash_op_block_func. Эта функция запретит кэш на CPU B и сигнализирует о запрете кэша установкой флага s_flash_op_can_start. Затем задача на CPU A также запретит кэш и приступит к выполнению операции с flash.

Когда осуществляется процесс операции над flash, прерывания все еще запускаются на ядрах CPU A и CPU B. При этом подразумевается, что весь код прерываний помещен в RAM. После добавления interrupt allocation API должен быть добавлен флаг для запроса запрета прерывания на время длительности операций flash.

Как только операция с flash завершится, функция на CPU установит другой флаг s_flash_op_complete, чтобы задача на CPU B смогла узнать об этом и снова разрешить работу кэша и освободить CPU. Затем функция на CPU A снова разрешит кэш на CPU A, а также вернет управление в вызывающий код.

Дополнительно все API-функции защищены мьютексом (s_flash_op_mutex).

В одноядерном рабочем окружении (когда разрешена опция CONFIG_FREERTOS_UNICORE), Вам нужно запретить оба кэша, чтобы не было возможности обмена данными между ядрами CPU.

[Справочник по API SPI Flash]

Заголовочный файл: components/spi_flash/include/esp_flash_spi_init.h.

Функция Описание
spi_bus_add_flash_device Добавляет устройство SPI Flash на шину SPI. Эта шина должна быть предварительно инициализирована вызовом spi_bus_initialization.
spi_bus_remove_flash_device Удалит устройство SPI Flash с шины SPI.

Заголовочный файл: components/spi_flash/include/esp_flash.h.

Функция Описание
esp_flash_init Инициализирует интерфейс микросхемы SPI flash. Эта функция должна быть вызвана перед любой другой API-функцией для этой микросхемы.
esp_flash_chip_driver_initialized Проверяет, установлен ли драйвер микросхемы SPI flash.
esp_flash_read_id Считывает flash ID (идентификатор микросхемы flash) с помощью команды "RDID" SPI flash. Это ID представлен 24-разрядным значением. Младшие 16 бит id это идентификатор микросхемы (chip ID), старшие 8 бит это идентификатор производителя (manufacturer ID).
esp_flash_get_size Определяет размер микросхемы памяти по flash ID.
esp_flash_read_unique_chip_id Считывает уникальный идентификатор (unique ID) с помощью общей команды "RDUID" SPI flash. ID здесь 64-разрядное значение.
esp_flash_erase_chip Стирает содержимое микросхемы flash.
esp_flash_erase_region Сотрет регион памяти микросхемы flash. Размер сектора указывается полем chip->drv->sector_size (обычно 4096 байт). Будет возвращено значение ESP_ERR_INVALID_ARG, если параметры начала и длины не делится нацело на этот размер. Стирание производится с использованием режима стирания блока (multi-sector), когда это возможно (размер блока задается полем chip->drv->block_erase_size field, обычно 65536 байт). Остальные секторы стираются индивидуальными командами очистки сектора.
esp_flash_get_chip_write_protect Возвратит статус, защищена ли микросхема целиком от записи.
esp_flash_set_chip_write_protect Установит защиту от записи для микросхемы SPI flash. Некоторые микросхемы могут потрбовать для этого отключения и включения питания перед тем, как может быть очищен статус защиты от записи. Иначе защита от записи может быть снята последующим вызовом этой функции.
esp_flash_get_protectable_regions Чтение списка индивидуально защищенных регионов микросхемы SPI flash.
esp_flash_get_protected_region Определяет, защищен ли регион микросхемы SPI flash.
esp_flash_set_protected_region Обновляет статус защиты для региона микросхемы SPI flash.
esp_flash_read Считывает данные из микросхемы SPI flash. Здесь нет ограничения на выравнивание буфера, адреса или длины.
esp_flash_write Записывает данные в микросхему SPI flash. Здесь нет ограничения на выравнивание буфера, адреса или длины.
esp_flash_write_encrypted Шифрует и записывает данные в микросхему SPI flash с использованием блока аппаратного шифрования flash.
esp_flash_read_encrypted Читает и расшифровывает данные из микросхемы SPI flash с использованием блока аппаратного шифрования flash.
esp_flash_is_quad_mode Возвратит true, если был сконфигурирован режим Quad I/O или Quad Fast Read.

Заголовочный файл: components/spi_flash/include/esp_spi_flash.h.

Функция Описание
spi_flash_wrap_set Установит режим wrap для flash.
spi_flash_init Инициализирует драйвер доступа SPI flash. Эта функция должна быть вызвана только 1 раз перед тем, как может быть вызвана любая другая функция spi_flash_*. В настоящее время эта функция вызывается кодом startup. Эту функцию не нужно вызывать из кода приложения.
spi_flash_get_chip_size Получает размер микросхемы flash, как это установлено в заголовке двоичного образа приложения.
spi_flash_erase_sector Стирает сектор flash.
spi_flash_erase_range Стирает диапазон секторов flash.
spi_flash_write Записывает данные в микросхему flash.
spi_flash_write_encrypted Записывает шифрованные данные на flash.
spi_flash_read Чтение данных из flash.
spi_flash_read_encrypted Чтение данных из Encrypted Flash. Если разрешено шифрование flash, то эта функция будет прозрачно расшифровать читаемые данные. Если шифрование flash не разрешено, то эта функция ведет себя так же, как и функция spi_flash_read(). См. esp_flash_encryption_enabled() для проверки, разрешено ли шифрование.
spi_flash_mmap Отображает регион памяти flash на адресное пространство данных или инструкций. Эта функция выделяет достаточное количество страниц 64kB MMU и конфигурирует их для отображения требуемой области памяти flash на адресное пространство. Этот вызов может повторно использовать страницы MMU, которые уже обеспечивают требуемое отображение. Как и в случае с любым выделением памяти (allocator), если интенсивно используются вызовы mmap/munmap, то адресное пространство может стать фрагментированным. Для решения проблем с выделением страниц используйте функцию spi_flash_mmap_dump().
spi_flash_mmap_pages Отображает последовательности страниц памяти flash на адресное пространство данных или инструкций. Эта функция выделяет достаточное количество страниц 64kB MMU и конфигурирует их для последовательного отображения указанных страниц памяти flash на адресное пространство. В этом отношении spi_flash_mmap_pages работает подобно spi_flash_mmap(), но позволяет отобразить набор страниц (который может быть не последовательным) на непрерывный регион памяти.
spi_flash_munmap Освободит регион, раннее полученный использованием spi_flash_mmap.
spi_flash_mmap_dump Отобразит информацию по отображенным регионам памяти. Эта функция выведет список дескрипторов, полученный с помощью spi_flash_mmap, вместе с диапазоном страниц, выделенных для каждого дескриптора. Этот вызов также перечислит все ненулевые записи таблицы MMU и соответствующие контрольные счетчики.
spi_flash_mmap_get_free_pages Получит количество свободных страниц, которые могут быть отображены (mmap). Эта функция вернет количество доступных страницы в таблице MMU. Функция может быть полезна перед реальным вызовом функции spi_flash_mmap (которая отобразит диапазон памяти flash на память DCache или ICache) чтобы проверить, достаточно ли места для отображения.
spi_flash_cache2phys По указанному адресу памяти, куда отображена flash, возвратит соответствующее физическое смещение в памяти flash. Адрес кэша не назначается через spi_flash_mmap(), может быть найден любой адрес отображенного пространства flash.
spi_flash_phys2cache По указанному физическому смещению в flash возвратит адрес в адресном пространстве, на который этот адрес flash отображен. Физический адрес не обязательно должен быть назначен через spi_flash_mmap(), может быть найден любой адрес в flash.
spi_flash_cache_enabled Проверит во время выполнения кода (runtime), разрешен ли кэш на обоих ядрах CPU.
spi_flash_enable_cache Заново разрешает кэш для ядра, указанного в параметре cpuid.
spi_flash_guard_set Установит функции защиты для доступа к flash.
spi_flash_guard_get Получит функции защиты, которые используются для доступа к flash.

[Справочник по API таблицы разделов]

Заголовочный файл: components/spi_flash/include/esp_partition.h.

Функция Описание
esp_partition_find Найдет раздел на основе одного или большего количества параметров.
esp_partition_find_first Найдет первый раздел на основе одного или большего количества параметров.
esp_partition_get Получит структуру esp_partition_t для указанного раздела.
esp_partition_next Переместит итератор на следующий найденный раздел. После этого вызова любые ранее сделанные копии этого итератора станут недопустимыми.
esp_partition_iterator_release Освободит итератор раздела.
esp_partition_verify Проверит данные раздела. По указателю на данные раздела будет выполнена проверка, существует ли этот раздел в таблице разделов (по заполненности всех полей). Эта функция также полезна для получения данных раздела, которые могут быть в буфере RAM, и преобразования их в указатель на данные постоянного раздела, хранящиеся в памяти flash. Указатели, возвращенные этой функцией, могут быть непосредственно сравнены с адресом любого указателя, возвращенного из esp_partition_get().
esp_partition_read Считывает данные из раздела. Разделы, помеченные флагом шифрования, будут автоматически считывать и расшифровывать данные с использованием кеширования.
esp_partition_write Записывает данные в раздел. Перед записью данных необходимо стереть соответствующий регион на flash. Это может быть сделано функцией esp_partition_erase_range. Разделы, помеченные флагом шифрования, будут автоматически записаны функцией spi_flash_write_encrypted(). Если запись осуществляется на зашифрованный раздел, то все смещения для записи и все длины данных в байтах должны нацело делиться на 16. Подробности см. в описании функции spi_flash_write_encrypted(). Для незашифрованных разделов такого ограничения нет.
esp_partition_read_raw Считывает данные из раздела без какого-либо преобразования/дешифровки.
esp_partition_write_raw Записывает данные в раздел без какого-либо преобразования/шифрования. Перед записью данных необходимо стереть соответствующий регион на flash. Это может быть сделано функцией esp_partition_erase_range.
esp_partition_erase_range Стирает часть раздела.
esp_partition_mmap Конфигурирует MMU для отображения раздела на память данных. В отличие от функции spi_flash_mmap, которая требует базового адреса, выровненного на 64kB, эта функция не накладывает таких требований. Если смещение приводит к адресу flash, который не делится нацело на 64kB, то адрес будет округлен к нижней границе 64kB, чтобы отображенный регион включал запрашиваемый диапазон. Указатель, возвращаемый через аргумент out_ptr, будет подстроен для указания на требуемое смещение (не обязательно на начала отображенного региона). Чтобы освободить отображенную память, передайте в функцию spi_flash_munmap дескриптор, возвращенный через аргумент out_handle.
esp_partition_get_sha256 Получает цифровую подпись SHA-256 для требуемого раздела. Для приложений, к образу которых добавлена SHA-256, результатом будет добавленное к app-образу значение SHA-256. Перед возвратом хэш проверяется, и если содержимое приложения неправильное, то функция вернет ESP_ERR_IMAGE_INVALID. Для приложений без добавленной к образу подписи SHA-256, результатом будет SHA-256 всех байт образа приложения. Для разделов других типов результатом будет SHA-256 от всего раздела.
esp_partition_check_identity Проверяет идентичность двух разделов с помощью цифровой подписи SHA-256.
esp_partition_register_external Регистрирует раздел на внешней микросхеме flash. Эта API-функция позволяет обозначить как разделы определенные области внешних микросхем flash (идентифицируемые структурой esp_flash_t). Это дает возможность использовать их с компонентами, которые получают доступ к SPI flash через esp_partition API.
esp_partition_deregister_external Отменяет регистрацию раздела, которая была выполнена ранее вызовом esp_partition_register_external.

[Справочник по API шифрования flash]

Заголовочный файл: components/bootloader_support/include/esp_flash_encrypt.h.

Функция Описание
esp_flash_encryption_enabled Определяет, разрешено ли в настоящий момент аппаратное шифрование flash. Шифрование flash разрешается, если у FLASH_CRYPT_CNT efuse нечетное количество установленных бит.
esp_flash_encrypt_check_and_update Вернет ESP_OK, если все операции были успешны, или ESP_ERR_INVALID_STATE, если была фатальная ошибка при шифровании всех разделов.
esp_flash_encrypt_region Шифрование по месту блока секторов flash.
esp_flash_write_protect_crypt_cnt Защита от записи FLASH_CRYPT_CNT. Предназначено для вызова как часть процесса загрузки, если разрешено шифрование flash encryption, но не используется безопасная загрузка (Secure Boot [12]). Это должно защитить от последовательной перепрошивки неавторизованного кода в случае отсутствия безопасной загрузки.
esp_get_flash_encryption_mode Вернет режим шифрования flash. Эта API-функция вызывается во время процесса загрузки, но также может быть вызвана приложением для проверки текущего режима шифрования ESP32.
esp_flash_encryption_init_checks Проверяет режим шифрования flash во время запуска (startup).
esp_flash_encryption_enable_secure_features Установит все функции безопасности eFuse, относящиеся к шифрованию flash.
esp_flash_encryption_set_release_mode Переключит шифрование памяти SPI flash (Flash Encryption) из состояния "Development" в состояние "Release".

Подробное описание типов данных, макросов и API-функций см. документацию [1].

[Словарик]

APP CPU, PRO CPU условное обозначение двух ядер ESP32, на которые в примерах среды разработки ESP-IDF возлагаются различные задачи приложения (PRO это ядро для обработки кода протоколов, APP это ядро для обработки кода приложения).

MMU Memory Management Unit, блок управления памятью.

OTA Over The Air, технология загрузки (обновления) по радиоканалу.

[Ссылки]

1. ESP32 SPI Flash API site:docs.espressif.com.
2. ESP32: таблицы разделов.
3. ESP32 Optional features for flash site:docs.espressif.com.
4. ESP32 Overriding Default Chip Drivers site:docs.espressif.com.
5. ESP32: процесс запуска приложения.
6. Конфигурация проекта ESP-IDF.
7. ESP32 Memory Types site:docs.espressif.com.
8. ESP32 SPI Master Driver site:docs.espressif.com.
9. ESP32 Flash Encryption site:docs.espressif.com.
10. ESP32: обновление по радиоканалу (OTA).
11. ESP32: библиотека энергонезависимого хранилища данных.
12. ESP32 Secure Boot V1.

 

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


Защитный код
Обновить

Top of Page