Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кармин Новиелло - Освоение STM32.pdf
Скачиваний:
2743
Добавлен:
23.09.2021
Размер:
47.68 Mб
Скачать

Организация памяти

546

В таблице 5 перечислены типы и атрибуты памяти, имеющиеся в микроконтроллере STM32. Как мы увидим в следующей главе, встроенная кэш-память первого уровня в микроконтроллерах STM32F7 также позволяет определить области внешней памяти, доступной через контроллер FMC, как кэшируемые. Это значительно улучшает производительность, которую предлагает семейство микроконтроллеров.

Таблица 5: Атрибуты памяти для типовых памятей STM32

Память

Тип памяти

Атрибуты памяти

 

 

 

ПЗУ, Flash (памяти

Нормальная

Неразделяемая, сквозная запись C=1, B=0, TEX=0, S=0

программ)

память

 

Внутреннее SRAM

Нормальная

Разделяемая, сквозная запись C=1, B=0, TEX=0, S=1/S=0

 

память

 

Внешнее ОЗУ

Нормальная

Разделяемая, отложенная запись C=1, B=1, TEX=0,

(через FMC)

память

S=1/S=0

Периферийные

Память

Разделяемые памяти устройства C=0, B=1, TEX=0,

устройства

устройства

S=1/S=0

Таблица 6 показывает сравнение характеристик MPU в ядрах Cortex-M0+/3/4/7. Обход MPU (MPU bypass) – это функция, предлагаемая MPU для обхода прав на доступ к области, когда ЦПУ выполняет исключения NMI или HardFault. Например, MPU может быть использован как механизм для обнаружения лимита стека путем выделения небольшого пространства SRAM в конце стека, помеченного как недоступное. При достижении лимита стека обработчик HardFault может обойти ограничения MPU и использовать зарезервированное пространство SRAM для обработки отказов.

Таблица 6: Сравнение характеристик MPU в различных ядрах Cortex-M

 

Cortex®-M0+

Cortex®-M3/M4

Cortex®-M7

Число областей

8

8

8

Адрес области

Да

Да

Да

Размер области

От 256Байт до 4ГБ

От 32Байт до 4ГБ

От 32Байт до 4ГБ

Атрибуты области памяти

S, C, B, XN

TEX, S, C, B, XN

TEX, S, C, B, XN

Право доступа к области

Да

Да

Да

Отключение подобласти

Да

Да

Да

Обход MPU для

Да

Да

Да

NMI/HardFault

 

 

 

Обработка исключений

Только HardFault

HardFault/MemManage

HardFault/MemManage

20.4.1. Программирование MPU с использованием CubeHAL

CubeHAL предоставляет весь необходимый уровень абстракции для программирования модуля MPU. Функция

void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init);

позволяет сконфигурировать область памяти. Все параметры области задаются экземпляром структуры MPU_Region_InitTypeDef, которая определена следующим образом:

typedef struct {

 

 

 

 

uint8_t

Enable;

/*

Задает

состояние области.

*/

uint8_t

Number;

/*

Задает

номер защищаемой области.

*/

Организация памяти

 

 

547

uint32_t BaseAddress;

/* Задает базовый адрес защищаемой области.

*/

uint8_t

Size;

/* Задает размер защищаемой области.

*/

uint8_t

SubRegionDisable;

/* Задает номер защищаемой подобласти для отключения. */

uint8_t

TypeExtField;

/* Задает уровень поля TEX.

*/

uint8_t

AccessPermission;

/* Задает тип права

доступа к области.

*/

uint8_t

DisableExec;

/* Задает состояние

доступа к инструкции.

*/

uint8_t

IsShareable;

/* Задает состояние

разделяемости защищенной области. */

uint8_t

IsCacheable;

/* Задает состояние

кэшируемости защищенной области. */

uint8_t

IsBufferable

/* Задает состояние

буферизируемости защищенной

 

 

 

области.

 

*/

} MPU_Region_InitTypeDef;

 

 

 

Давайте проанализируем наиболее важные поля данной структуры.

Enable: задает состояние области и может принимать значения MPU_REGION_ENABLE

и MPU_REGION_DISABLE.

Number: идентификатор области, и он может быть от 0 до 7.

BaseAddress: соответствует базовому адресу области. В Cortex-M0+ этот адрес дол-

жен быть выровнен по словам.

Size: задает размер области и соответствует всем степеням двойки от 25 до 232.

CubeHAL определяет набор из 27 макросов, начиная от MPU_REGION_SIZE_32B до

MPU_REGION_SIZE_4GB. В файле stm32XXxx_hal_cortex.h можно посмотреть полный

перечень макросов.

AccessPermission: задает атрибуты прав доступа области и может принимать зна-

чения, перечисленные в таблице 7.

DisableExec: указывает, возможно ли выполнить код внутри области. Может

принимать значения MPU_INSTRUCTION_ACCESS_ENABLE и MPU_INSTRUCTION_ACCESS_DISABLE.

IsShareable: указывает, имеет ли область атрибут разделяемая, и может прини-

мать значения MPU_ACCESS_SHAREABLE и MPU_ACCESS_NOT_SHAREABLE.

IsCacheable: указывает, имеет ли область атрибут кэшируемая, и может прини-

мать значения MPU_ACCESS_CACHEABLE и MPU_ACCESS_NOT_CACHEABLE.

IsBufferable: указывает, имеет ли область атрибут буферизируемая, и может при-

нимать значения MPU_ACCESS_BUFFERABLE и MPU_ACCESS_NOT_BUFFERABLE.

Таблица 7: Макросы CubeHAL для определения прав доступа к области

Права доступа

Описание

 

 

MPU_REGION_NO_ACCESS

Любая попытка доступа к области сгенерирует отказ доступа

MPU_REGION_PRIV_RW

Доступ только для привилегированного ПО

MPU_REGION_PRIV_RW_URO

Запись от непривилегированного ПО сгенерирует отказ доступа

MPU_REGION_FULL_ACCESS

Полный доступ к области

MPU_REGION_PRIV_RO

Чтение только привилегированным ПО

MPU_REGION_PRIV_RO_URO

Только чтение, привилегированным и непривилегированным ПО

MPU должен быть отключен перед конфигурацией какой-либо области памяти (или перед изменением ее атрибутов). Для выполнения этой операции HAL предоставляет функцию:

void HAL_MPU_Disable(void);

Организация памяти

548

в то время как для включения MPU мы используем функцию:

void HAL_MPU_Enable(uint32_t MPU_Control);

Параметр MPU_Control задает режим управления MPU во время HardFault, NMI, FAULTMASK и привилегированного доступа к памяти по умолчанию. Может принимать значения, перечисленные в таблице 8. Важно отметить, что исключение отказа памяти MemFault разрешается автоматически после включения MPU.

Таблица 8: Макросы CubeHAL для определения управления MPU во время HardFault, NMI и FAULTMASK

Права доступа

Описание

 

 

MPU_HFNMI_PRIVDEF_NONE

Карта памяти по умолчанию используется для привилегирован-

 

ного доступа и предполагает роль фоновой области (также назы-

 

ваемой «областью -1», где «-1» – идентификатор области). Доступ

 

ко всем 4 ГБ тем самым запрещен для непривилегированного

 

кода, за исключением тех областей, где он явно разрешен.

MPU_HARDFAULT_NMI

MPU отключен при возникновении исключений HardFault и NMI.

MPU_PRIVILEGED_DEFAULT

Фоновая область отключена, и любой доступ, не покрытый какой-

 

либо из включенных областей, вызовет отказ.

MPU_HFNMI_PRIVDEF

MPU включен при возникновении исключений HardFault и NMI.

1 MPU_Region_InitTypeDef MPU_InitStruct;

2

3/* Отключение MPU */

4HAL_MPU_Disable();

6/* Конфигурация области ОЗУ как Области №0 размером 8КБ и с доступом R/W */

7MPU_InitStruct.Enable = MPU_REGION_ENABLE;

8MPU_InitStruct.BaseAddress = 0x20000A00;

9MPU_InitStruct.Size = MPU_REGION_SIZE_32B;

10MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO_URO;

11MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

12MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;

13MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

14MPU_InitStruct.Number = MPU_REGION_NUMBER0;

15MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

16MPU_InitStruct.SubRegionDisable = 0x00;

17MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

18HAL_MPU_ConfigRegion(&MPU_InitStruct);

19

20/* Определение указателя на первое слово защищенной области */

21volatile uint32_t *p = (uint32_t*)0x20000A00;

22*p = 0xDDEEFF00;

23

24/* Повторное включение MPU и включение фоновой области */

25HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

26

27if(*p != 0xDDEEFF00)

28asm("BKPT #0");

Организация памяти

549

29

30*p = 0xAABBCCDD; // Это сгенерирует отказ MemManage

В предыдущем фрагменте кода показано, как определить область памяти в SRAM и предотвратить доступ к ней в режиме записи как для привилегированного, так и для непривилегированного кода. Область начинается с адреса 0x2000 0A00 и занимает 32 Байт. В строке 21 определяется указатель на начало этой области, а содержимое первого слова изменяется в строке 22. Затем включается MPU, и атрибуты области не позволяют коду изменять его содержимое. Условие if в строке 27 не выполняется, поскольку первое слово области содержит значение 0xDDEE FF00. Однако команда в строке 30 сгенерирует отказ MemManage из-за атрибута области «только чтение».