mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-02 14:23:19 +08:00
[arm][cortex-m4] Add hardware stack guard support
Enable RT_USING_HW_STACK_GUARD on Cortex-M4, which was previously only available on Cortex-M7 and Cortex-M33. Core porting (libcpu/arm/cortex-m4/): - Add mpu.c/mpu.h/mputype.h aligned with the Cortex-M7 MPU layer. The only difference is the default memory type attribute: Cortex-M4 has no L1 cache, so the cacheability bits are reduced to three cases. - Add rt_hw_stack_guard_init() to cpuport.c. - Add missing #include <rtconfig.h> to context_gcc.S and invoke rt_hw_mpu_table_switch() in the PendSV context switch path. - Update SConscript to exclude mpu.c when memory protection is disabled. BSP reference (bsp/stm32/stm32f407-fk407m2-zgt6/): - board.h: include rtthread.h and define NUM_STATIC_REGIONS. - board.c: define static_regions[] marking the Flash region read-only, guarded by RT_USING_MEM_PROTECTION so it is not enabled by default.
This commit is contained in:
@@ -11,50 +11,61 @@
|
||||
#include <board.h>
|
||||
#include <drv_common.h>
|
||||
|
||||
#ifdef RT_USING_MEM_PROTECTION
|
||||
#include "mprotect.h"
|
||||
|
||||
rt_mem_region_t static_regions[NUM_STATIC_REGIONS] = {
|
||||
/* Flash region, read only */
|
||||
{
|
||||
.start = (void *)STM32_FLASH_START_ADRESS,
|
||||
.size = (rt_size_t)STM32_FLASH_SIZE,
|
||||
.attr = RT_MEM_REGION_P_RX_U_RX,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
void SystemClock_Config(void)
|
||||
{
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
|
||||
|
||||
/**Configure the main internal regulator output voltage
|
||||
*/
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
/**Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE
|
||||
|RCC_OSCILLATORTYPE_LSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
|
||||
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 168;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 7;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/**Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||||
/**Configure the main internal regulator output voltage
|
||||
*/
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
/**Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_LSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
|
||||
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 168;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 7;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/**Initializes the CPU, AHB and APB busses clocks
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||||
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,31 +11,36 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <stm32f4xx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define STM32_SRAM_SIZE (128)
|
||||
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
|
||||
#define STM32_SRAM_SIZE (128)
|
||||
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
|
||||
|
||||
#define STM32_FLASH_START_ADRESS ((uint32_t)0x08000000)
|
||||
#define STM32_FLASH_SIZE (1024 * 1024)
|
||||
#define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE))
|
||||
#define STM32_FLASH_START_ADRESS ((uint32_t)0x08000000)
|
||||
#define STM32_FLASH_SIZE (1024 * 1024)
|
||||
#define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE))
|
||||
|
||||
#if defined(__ARMCC_VERSION)
|
||||
extern int Image$$RW_IRAM1$$ZI$$Limit;
|
||||
#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
|
||||
#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
|
||||
#elif __ICCARM__
|
||||
#pragma section="CSTACK"
|
||||
#define HEAP_BEGIN (__segment_end("CSTACK"))
|
||||
#pragma section = "CSTACK"
|
||||
#define HEAP_BEGIN (__segment_end("CSTACK"))
|
||||
#else
|
||||
extern int __bss_end;
|
||||
#define HEAP_BEGIN ((void *)&__bss_end)
|
||||
#define HEAP_BEGIN ((void *)&__bss_end)
|
||||
#endif
|
||||
|
||||
#define HEAP_END STM32_SRAM_END
|
||||
#define HEAP_END STM32_SRAM_END
|
||||
|
||||
#ifdef RT_USING_MEM_PROTECTION
|
||||
#define NUM_STATIC_REGIONS 1
|
||||
#endif
|
||||
|
||||
void SystemClock_Config(void);
|
||||
|
||||
|
||||
@@ -21,6 +21,19 @@ if rtconfig.PLATFORM in ['gcc', 'llvm-arm']:
|
||||
if rtconfig.PLATFORM in ['iccarm']:
|
||||
src += Glob('*_iar.S')
|
||||
|
||||
using_mpu = (
|
||||
GetDepend('RT_USING_MEM_PROTECTION') or
|
||||
GetDepend('RT_USING_HW_STACK_GUARD')
|
||||
)
|
||||
|
||||
if using_mpu:
|
||||
if rtconfig.PLATFORM not in ['gcc', 'llvm-arm']:
|
||||
raise RuntimeError(
|
||||
'Cortex-M4 memory protection currently supports GCC only'
|
||||
)
|
||||
else:
|
||||
SrcRemove(src, 'mpu.c')
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
.cpu cortex-m4
|
||||
.syntax unified
|
||||
.thumb
|
||||
@@ -155,6 +157,13 @@ switch_to_thread:
|
||||
BICNE lr, lr, #0x10 /* lr &= ~(1 << 4), set FPCA. */
|
||||
#endif
|
||||
|
||||
#if defined (RT_USING_MEM_PROTECTION)
|
||||
PUSH {r0-r3, r12, lr}
|
||||
BL rt_thread_self
|
||||
BL rt_hw_mpu_table_switch
|
||||
POP {r0-r3, r12, lr}
|
||||
#endif
|
||||
|
||||
pendsv_exit:
|
||||
/* restore interrupt */
|
||||
MSR PRIMASK, r2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-09-25 tangzz98 the first version
|
||||
* 2026-08-23 RT-Thread add cortex-m4 support
|
||||
*/
|
||||
|
||||
#ifndef __MPU_H__
|
||||
#define __MPU_H__
|
||||
|
||||
#ifdef RT_USING_MEM_PROTECTION
|
||||
|
||||
#include <board.h>
|
||||
|
||||
#define MPU_MIN_REGION_SIZE 32U
|
||||
|
||||
/* MPU attributes for configuring data region permission.
|
||||
* These are identical to Cortex-M7 because both cores implement the
|
||||
* ARMv7-M MPU with the same AP/XN bit layout in the RASR register. */
|
||||
/* Privileged No Access, Unprivileged No Access */
|
||||
#define P_NA_U_NA ((0x0 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk | MPU_RASR_XN_Msk)
|
||||
/* Privileged Read Write, Unprivileged No Access */
|
||||
#define P_RW_U_NA ((0x1 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk | MPU_RASR_XN_Msk)
|
||||
/* Privileged Read Write, Unprivileged Read Only */
|
||||
#define P_RW_U_RO ((0x2 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk | MPU_RASR_XN_Msk)
|
||||
/* Privileged Read Write, Unprivileged Read Write */
|
||||
#define P_RW_U_RW ((0x3 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk | MPU_RASR_XN_Msk)
|
||||
/* Privileged Read Only, Unprivileged No Access */
|
||||
#define P_RO_U_NA ((0x5 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk | MPU_RASR_XN_Msk)
|
||||
/* Privileged Read Only, Unprivileged Read Only */
|
||||
#define P_RO_U_RO ((0x6 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk | MPU_RASR_XN_Msk)
|
||||
|
||||
/* MPU attributes for configuring code region permission */
|
||||
/* Privileged Read Write Execute, Unprivileged Read Write Execute */
|
||||
#define P_RWX_U_RWX ((0x3 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
|
||||
/* Privileged Read Write Execute, Unprivileged Read Execute */
|
||||
#define P_RWX_U_RX ((0x2 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
|
||||
/* Privileged Read Write Execute, Unprivileged No Access */
|
||||
#define P_RWX_U_NA ((0x1 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
|
||||
/* Privileged Read Execute, Unprivileged Read Execute */
|
||||
#define P_RX_U_RX ((0x6 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
|
||||
/* Privileged Read Execute, Unprivileged No Access */
|
||||
#define P_RX_U_NA ((0x5 << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
|
||||
|
||||
/* MPU attributes for configuring memory type, cacheability and shareability.
|
||||
*
|
||||
* Unlike Cortex-M7, Cortex-M4 has no L1 cache, so the cacheability bits in
|
||||
* RASR only control memory ordering (strongly-ordered / device / normal)
|
||||
* rather than an actual cache. The full write-through / write-back taxonomy
|
||||
* used on M7 is therefore not needed here and is reduced to three types. */
|
||||
#define STRONGLY_ORDERED_SHAREABLE MPU_RASR_S_Msk
|
||||
#define STRONGLY_ORDERED_NON_SHAREABLE 0U
|
||||
#define DEVICE_SHAREABLE (MPU_RASR_B_Msk | MPU_RASR_S_Msk)
|
||||
#define DEVICE_NON_SHAREABLE MPU_RASR_B_Msk
|
||||
#define NORMAL_NON_CACHEABLE_SHAREABLE (MPU_RASR_C_Msk | MPU_RASR_S_Msk)
|
||||
#define NORMAL_NON_CACHEABLE MPU_RASR_C_Msk
|
||||
/* Sentinel marking an attribute that only carries the permission bits and
|
||||
* therefore needs the default memory type filled in later. */
|
||||
#define RESERVED ((2 << MPU_RASR_TEX_Pos) | MPU_RASR_B_Msk)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rt_thread_t thread; /* Thread that triggered exception */
|
||||
void *addr; /* Address of faulting memory access */
|
||||
rt_mem_region_t region; /* Configurations of the memory region containing the address */
|
||||
rt_uint8_t mmfsr; /* Content of MemManage Status Register */
|
||||
} rt_mem_exception_info_t;
|
||||
|
||||
typedef void (*rt_hw_mpu_exception_hook_t)(rt_mem_exception_info_t *);
|
||||
|
||||
#define RT_ARM_MEM_ATTR(perm, type) ((rt_mem_attr_t){ (perm) | (type) })
|
||||
|
||||
/* Convenient macros for configuring data region attributes with default memory type */
|
||||
#define RT_MEM_REGION_P_NA_U_NA RT_ARM_MEM_ATTR(P_NA_U_NA, RESERVED)
|
||||
#define RT_MEM_REGION_P_RW_U_RW RT_ARM_MEM_ATTR(P_RW_U_RW, RESERVED)
|
||||
#define RT_MEM_REGION_P_RW_U_RO RT_ARM_MEM_ATTR(P_RW_U_RO, RESERVED)
|
||||
#define RT_MEM_REGION_P_RW_U_NA RT_ARM_MEM_ATTR(P_RW_U_NA, RESERVED)
|
||||
#define RT_MEM_REGION_P_RO_U_RO RT_ARM_MEM_ATTR(P_RO_U_RO, RESERVED)
|
||||
#define RT_MEM_REGION_P_RO_U_NA RT_ARM_MEM_ATTR(P_RO_U_NA, RESERVED)
|
||||
|
||||
/* Convenient macros for configuring code region attributes with default memory type */
|
||||
#define RT_MEM_REGION_P_RWX_U_RWX RT_ARM_MEM_ATTR(P_RWX_U_RWX, RESERVED)
|
||||
#define RT_MEM_REGION_P_RWX_U_RX RT_ARM_MEM_ATTR(P_RWX_U_RX, RESERVED)
|
||||
#define RT_MEM_REGION_P_RWX_U_NA RT_ARM_MEM_ATTR(P_RWX_U_NA, RESERVED)
|
||||
#define RT_MEM_REGION_P_RX_U_RX RT_ARM_MEM_ATTR(P_RX_U_RX, RESERVED)
|
||||
#define RT_MEM_REGION_P_RX_U_NA RT_ARM_MEM_ATTR(P_RX_U_NA, RESERVED)
|
||||
|
||||
rt_bool_t rt_hw_mpu_region_valid(rt_mem_region_t *region);
|
||||
rt_err_t rt_hw_mpu_init(void);
|
||||
rt_err_t rt_hw_mpu_add_region(rt_thread_t thread, rt_mem_region_t *region);
|
||||
rt_err_t rt_hw_mpu_delete_region(rt_thread_t thread, rt_mem_region_t *region);
|
||||
rt_err_t rt_hw_mpu_update_region(rt_thread_t thread, rt_mem_region_t *region);
|
||||
rt_err_t rt_hw_mpu_exception_set_hook(rt_hw_mpu_exception_hook_t hook);
|
||||
void rt_hw_mpu_table_switch(rt_thread_t thread);
|
||||
|
||||
#endif /* RT_USING_MEM_PROTECTION */
|
||||
|
||||
#endif /* __MPU_H__ */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-09-25 tangzz98 the first version
|
||||
* 2026-08-23 RT-Thread add cortex-m4 support
|
||||
*/
|
||||
|
||||
#ifndef __MPUTYPE_H__
|
||||
#define __MPUTYPE_H__
|
||||
|
||||
#ifdef RT_USING_MEM_PROTECTION
|
||||
|
||||
#ifdef RT_USING_HW_STACK_GUARD
|
||||
#define NUM_DYNAMIC_REGIONS (2 + NUM_CONFIGURABLE_REGIONS)
|
||||
#else
|
||||
#define NUM_DYNAMIC_REGIONS (NUM_CONFIGURABLE_REGIONS)
|
||||
#endif
|
||||
|
||||
/* Cortex-M4 follows ARMv7-M, whose MPU programs the full attribute set
|
||||
* (access permission + memory type) through the single RASR register,
|
||||
* just like Cortex-M7. */
|
||||
typedef struct
|
||||
{
|
||||
rt_uint32_t rasr;
|
||||
} rt_mem_attr_t;
|
||||
|
||||
#endif /* RT_USING_MEM_PROTECTION */
|
||||
|
||||
#endif /* __MPUTYPE_H__ */
|
||||
Reference in New Issue
Block a user