diff --git a/Inc/HALAL/HALAL.hpp b/Inc/HALAL/HALAL.hpp index 9bea3a79f..fe4684068 100644 --- a/Inc/HALAL/HALAL.hpp +++ b/Inc/HALAL/HALAL.hpp @@ -37,6 +37,7 @@ #include "HALAL/Services/FMAC/FMAC.hpp" #include "HALAL/Models/MPUManager/MPUManager.hpp" +#include "HALAL/Models/MPU.hpp" #include "HALAL/Services/InfoWarning/InfoWarning.hpp" #include "HALAL/Services/Watchdog/Watchdog.hpp" diff --git a/Inc/HALAL/Models/MPU.hpp b/Inc/HALAL/Models/MPU.hpp new file mode 100644 index 000000000..93d19a728 --- /dev/null +++ b/Inc/HALAL/Models/MPU.hpp @@ -0,0 +1,449 @@ +/* + * MPU.hpp + * + * Created on: 10 dic. 2025 + * Author: Boris + * + * Memory Allocation Strategies: + * ============================== + * This system supports three distinct memory allocation methods that can coexist: + * + * 1. MANUAL ALLOCATION (via macros): + * Use D1_NC, D2_NC, D3_NC, D1_C, D2_C, D3_C macros for static/global variables. + * Example: D1_NC uint8_t my_buffer[100]; + * Placed in: .mpu_ram_dX_nc.user or .ram_dX.user sections + * + * 2. NEW MPU SYSTEM (compile-time allocation): + * Use MPUDomain::Buffer with compile-time buffer management. + * Automatically placed and sized by the Domain system. + * Placed in: .mpu_ram_dX_nc.buffer or .ram_dX.buffer sections + * + * 3. LEGACY MPUManager (runtime allocation): + * Use MPUManager::allocate_non_cached_memory() for dynamic allocation. + * Currently uses a 2KB pool in D3 non-cached memory. + * Placed in: .mpu_ram_d3_nc.legacy section + * + * These three methods are separated in the linker script to prevent overlap. + * All memory is properly configured by MPU regions as non-cached or cached. + */ + +#ifndef MPU_HPP +#define MPU_HPP + +#ifndef HALAL_MPUBUFFERS_MAX_INSTANCES // Define this in your build system if you need a different value +#define HALAL_MPUBUFFERS_MAX_INSTANCES 100 +#endif + +#include "C++Utilities/CppUtils.hpp" +#include "C++Utilities/CppImports.hpp" +#include "ErrorHandler/ErrorHandler.hpp" +#include "stm32h7xx_hal.h" +#include "HALAL/Models/MPUManager/MPUManager.hpp" + +// Defines for attributes +// Note1: Variables declared with these attributes will likely not be initialized by the startup +// Note2: These attributes can only be used for static/global variables +#define D1_NC __attribute__((section(".mpu_ram_d1_nc.user"))) +#define D2_NC __attribute__((section(".mpu_ram_d2_nc.user"))) +#define D3_NC __attribute__((section(".mpu_ram_d3_nc.user"))) +#define D1_C __attribute__((section(".ram_d1.user"))) +#define D2_C __attribute__((section(".ram_d2.user"))) +#define D3_C __attribute__((section(".ram_d3.user"))) + +// Define for RAM code +#define RAM_CODE __attribute__((section(".ram_code"))) + +// Memory Bank Symbols from Linker +extern "C" const uintptr_t __itcm_base; +extern "C" const size_t __itcm_size; +extern "C" const uintptr_t __dtcm_base; +extern "C" const size_t __dtcm_size; +extern "C" const uintptr_t __flash_base; +extern "C" const size_t __flash_size; +extern "C" const uintptr_t __ram_d1_base; +extern "C" const size_t __ram_d1_size; +extern "C" const uintptr_t __ram_d2_base; +extern "C" const size_t __ram_d2_size; +extern "C" const uintptr_t __ram_d3_base; +extern "C" const size_t __ram_d3_size; +extern "C" const uintptr_t __peripheral_base; +extern "C" const size_t __peripheral_size; + +// MPU Non-Cached Section Symbols from Linker +extern "C" const uintptr_t __mpu_d1_nc_start; +extern "C" const uintptr_t __mpu_d1_nc_end; +extern "C" const uintptr_t __mpu_d2_nc_start; +extern "C" const uintptr_t __mpu_d2_nc_end; +extern "C" const uintptr_t __mpu_d3_nc_start; +extern "C" const uintptr_t __mpu_d3_nc_end; + + +template +concept mpu_buffer_request = requires(typename T::domain d) { + typename T::buffer_type; + { T{ } } -> std::same_as; +}; + +// POD-like buffers that can safely live in static storage without custom destruction. +template +concept mpu_buffer_payload = + std::is_standard_layout_v && std::is_trivially_destructible_v; + +extern void compile_error(const char *msg); +struct MPUDomain { + + enum class MemoryDomain : uint8_t { + D1 = 1, // AXI SRAM (0x24000000) + D2 = 2, // SRAM 1/2/3 (0x30000000) + D3 = 3 // SRAM 4 (0x38000000) + }; + + enum class MemoryType : bool { + Cached = true, + NonCached = false + }; + + // Buffer Request + struct Entry { + MemoryDomain memory_domain; + MemoryType memory_type; + std::size_t alignment; + std::size_t size_in_bytes; + }; + + // Buffer Request Wrapper + template + struct Buffer { + using domain = MPUDomain; + using buffer_type = T; + Entry e; + + /** + * @brief Constructs a Buffer entry for a type T with explicit parameter. + * @tparam T The type for which the buffer is requested. Must be a POD type. + * @param type The memory type (Cached or NonCached). + * @param domain The memory domain where the buffer should be allocated (Defaults to D1, since it is the largest and fastest). + * @param force_cache_alignment If true, forces the buffer to be cache line aligned (32 bytes, takes the rest as padding). + */ + consteval Buffer(MemoryType type = MemoryType::NonCached, + MemoryDomain mem_domain = MemoryDomain::D1, + bool force_cache_alignment = false) + : e{ + mem_domain, + type, + force_cache_alignment ? 32 : alignof(T), + sizeof(T)} + { + static_assert(alignof(T) <= 32, "Requested type has alignment greater than cache line size (32 bytes)."); + static_assert(std::ranges::find(alignments, alignof(T)) != std::ranges::end(alignments), + "Requested type has alignment not supported by MPU buffer system."); + } + + /** + * @brief Constructs a Buffer from an Entry struct (allows named parameter syntax). + * @param entry The Entry with all buffer requirements specified. + */ + consteval Buffer(Entry entry) : e(entry) { + static_assert(entry.alignment <= 32, "Requested alignment greater than cache line size (32 bytes)."); + static_assert(std::ranges::find(alignments, entry.alignment) != std::ranges::end(alignments), + "Requested alignment not supported by MPU buffer system."); + // Verify size matches sizeof(T) + if (entry.size_in_bytes != sizeof(T)) { + compile_error("Entry size_in_bytes must match sizeof(T)"); + } + } + + template + consteval std::size_t inscribe(Ctx &ctx) const { + return ctx.template add(e, this); + } + }; + + + static constexpr std::size_t max_instances = HALAL_MPUBUFFERS_MAX_INSTANCES; + + struct Config { + uint32_t offset; // Offset relative to the start of the domain buffer + std::size_t size; + MemoryDomain domain; + MemoryType type; + }; + + // Helper to calculate sizes needed for static arrays + struct DomainSizes { + size_t d1_nc_total = 0; + size_t d1_c_total = 0; + size_t d2_nc_total = 0; + size_t d2_c_total = 0; + size_t d3_nc_total = 0; + size_t d3_c_total = 0; + }; + + static consteval uint32_t align_up(uint32_t val, size_t align) { + return (val + align - 1) & ~(align - 1); // Align up to 'align' leaving the minimum padding + } + + + static consteval DomainSizes calculate_total_sizes(std::span configs) { + DomainSizes sizes; + for (const auto& cfg : configs) { + size_t end = cfg.offset + cfg.size; + if (cfg.domain == MemoryDomain::D1) { + if(cfg.type == MemoryType::NonCached) sizes.d1_nc_total = std::max(sizes.d1_nc_total, end); + else sizes.d1_c_total = std::max(sizes.d1_c_total, end); + } + else if (cfg.domain == MemoryDomain::D2) { + if(cfg.type == MemoryType::NonCached) sizes.d2_nc_total = std::max(sizes.d2_nc_total, end); + else sizes.d2_c_total = std::max(sizes.d2_c_total, end); + } + else if (cfg.domain == MemoryDomain::D3) { + if(cfg.type == MemoryType::NonCached) sizes.d3_nc_total = std::max(sizes.d3_nc_total, end); + else sizes.d3_c_total = std::max(sizes.d3_c_total, end); + } + } + // Align totals to 32 bytes, just in case + sizes.d1_nc_total = align_up(sizes.d1_nc_total, 32); + sizes.d1_c_total = align_up(sizes.d1_c_total, 32); + sizes.d2_nc_total = align_up(sizes.d2_nc_total, 32); + sizes.d2_c_total = align_up(sizes.d2_c_total, 32); + sizes.d3_nc_total = align_up(sizes.d3_nc_total, 32); + sizes.d3_c_total = align_up(sizes.d3_c_total, 32); + return sizes; + } + + template + static consteval std::array build(std::span entries) { + if constexpr (N == 0) { + return {}; + } else { + std::array cfgs{}; + + uint32_t offsets_nc[3] = {}; // D1, D2, D3 + uint32_t offsets_c[3] = {}; // D1, D2, D3 + uint32_t assigned_offsets[N]; + + for (size_t align : alignments) { + for (size_t i = 0; i < N; i++) { + if (entries[i].alignment == align) { + size_t d_idx = static_cast(entries[i].memory_domain) - 1; + if (entries[i].memory_type == MemoryType::NonCached) { + offsets_nc[d_idx] = align_up(offsets_nc[d_idx], align); + assigned_offsets[i] = offsets_nc[d_idx]; + offsets_nc[d_idx] += entries[i].size_in_bytes; + } else { + offsets_c[d_idx] = align_up(offsets_c[d_idx], align); + assigned_offsets[i] = offsets_c[d_idx]; + offsets_c[d_idx] += entries[i].size_in_bytes; + } + } + } + } + + /* Build Configs */ + for (std::size_t i = 0; i < N; i++) { + cfgs[i].size = entries[i].size_in_bytes; + cfgs[i].domain = entries[i].memory_domain; + cfgs[i].type = entries[i].memory_type; + cfgs[i].offset = assigned_offsets[i]; + } + + return cfgs; + } + } + + struct Instance { + void* ptr; + std::size_t size; + + template + auto& construct(Args&&... args) { + using T = typename std::remove_cvref_t::buffer_type; + return *new (ptr) T(std::forward(args)...); + } + + template + auto* as() { + using T = typename std::remove_cvref_t::buffer_type; + return static_cast(ptr); + } + }; + + template + static auto& construct(Args&&... args) { + return Board::template instance_of().template construct(std::forward(args)...); + } + + template + static auto* as() { + return Board::template instance_of().template as(); + } + + + template cfgs> + struct Init { + static inline std::array instances{}; + + static constexpr auto Sizes = calculate_total_sizes(cfgs); + + // Sections defined in Linker Script (aligned to 32 bytes just in case) + __attribute__((section(".mpu_ram_d1_nc.buffer"))) alignas(32) + static inline uint8_t d1_nc_buffer[Sizes.d1_nc_total > 0 ? Sizes.d1_nc_total : 1]; + __attribute__((section(".ram_d1.buffer"))) alignas(32) + static inline uint8_t d1_c_buffer[Sizes.d1_c_total > 0 ? Sizes.d1_c_total : 1]; + + __attribute__((section(".mpu_ram_d2_nc.buffer"))) alignas(32) + static inline uint8_t d2_nc_buffer[Sizes.d2_nc_total > 0 ? Sizes.d2_nc_total : 1]; + __attribute__((section(".ram_d2.buffer"))) alignas(32) + static inline uint8_t d2_c_buffer[Sizes.d2_c_total > 0 ? Sizes.d2_c_total : 1]; + + __attribute__((section(".mpu_ram_d3_nc.buffer"))) alignas(32) + static inline uint8_t d3_nc_buffer[Sizes.d3_nc_total > 0 ? Sizes.d3_nc_total : 1]; + __attribute__((section(".ram_d3.buffer"))) alignas(32) + static inline uint8_t d3_c_buffer[Sizes.d3_c_total > 0 ? Sizes.d3_c_total : 1]; + + static void init() { + HAL_MPU_Disable(); + configure_static_regions(); + + // Dynamic Configuration based on Linker Symbols + configure_dynamic_region((uintptr_t)__mpu_d1_nc_start, (uintptr_t)__mpu_d1_nc_end, MPU_REGION_NUMBER3); + configure_dynamic_region((uintptr_t)__mpu_d2_nc_start, (uintptr_t)__mpu_d2_nc_end, MPU_REGION_NUMBER5); + configure_dynamic_region((uintptr_t)__mpu_d3_nc_start, (uintptr_t)__mpu_d3_nc_end, MPU_REGION_NUMBER7); + + // Assign pointers + uint8_t* bases_nc[3] = { &d1_nc_buffer[0], &d2_nc_buffer[0], &d3_nc_buffer[0] }; + uint8_t* bases_c[3] = { &d1_c_buffer[0], &d2_c_buffer[0], &d3_c_buffer[0] }; + + for (std::size_t i = 0; i < N; i++) { + const auto &cfg = cfgs[i]; + auto &inst = instances[i]; + + if (cfg.domain == MemoryDomain::D1 || cfg.domain == MemoryDomain::D2 || cfg.domain == MemoryDomain::D3) { + size_t d_idx = static_cast(cfg.domain) - 1; + + if (cfg.type == MemoryType::NonCached) { + inst.ptr = bases_nc[d_idx] + cfg.offset; + } else { + inst.ptr = bases_c[d_idx] + cfg.offset; + } + inst.size = cfg.size; + } + } + + HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); + SCB_EnableICache(); + SCB_EnableDCache(); + } + }; + + private: + static constexpr std::size_t alignments[6] = {32, 16, 8, 4, 2, 1}; + + static void configure_dynamic_region(uintptr_t start, uintptr_t end, uint8_t region_num) { + if (end <= start) return; + configure_region(start, end - start, region_num, + MPU_TEX_LEVEL1, MPU_REGION_FULL_ACCESS, MPU_INSTRUCTION_ACCESS_DISABLE, + MPU_ACCESS_SHAREABLE, MPU_ACCESS_NOT_CACHEABLE, MPU_ACCESS_NOT_BUFFERABLE); + } + + static void configure_static_regions() { + MPU_Region_InitTypeDef MPU_InitStruct = {0}; + + // Background (No Access) - Covers all memory not explicitly defined by a further region + // Doesn't use configure_region helper since that uses an uint32_t size, we need 4GB here... + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.BaseAddress = 0x00; + MPU_InitStruct.Size = MPU_REGION_SIZE_4GB; + MPU_InitStruct.SubRegionDisable = 0x00; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + // Peripherals (Device, Buffered) + // Guarded against speculative execution and cache + configure_region(__peripheral_base, __peripheral_size, MPU_REGION_NUMBER8, + MPU_TEX_LEVEL0, MPU_REGION_FULL_ACCESS, MPU_INSTRUCTION_ACCESS_DISABLE, + MPU_ACCESS_SHAREABLE, MPU_ACCESS_NOT_CACHEABLE, MPU_ACCESS_BUFFERABLE); + + // Flash (Normal, Cacheable) + // TEX=1, C=1, B=0: Normal, Write-Through (Read optimized) + // Not Shareable to allow full caching + configure_region(__flash_base, __flash_size, MPU_REGION_NUMBER1, + MPU_TEX_LEVEL1, MPU_REGION_FULL_ACCESS, MPU_INSTRUCTION_ACCESS_ENABLE, + MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_NOT_BUFFERABLE); + + // DTCM (Normal, Cacheable) + // Uses Normal memory attributes. TCM access is uncached by hardware, but "Normal" allows unaligned access. + configure_region(__dtcm_base, __dtcm_size, MPU_REGION_NUMBER10, + MPU_TEX_LEVEL1, MPU_REGION_FULL_ACCESS, MPU_INSTRUCTION_ACCESS_DISABLE, + MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); + + // ITCM (Normal, Cacheable) + configure_region(__itcm_base, __itcm_size, MPU_REGION_NUMBER11, + MPU_TEX_LEVEL1, MPU_REGION_FULL_ACCESS, MPU_INSTRUCTION_ACCESS_ENABLE, + MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); + + // D1 RAM Cached (Normal, WBWA) + // TEX=1, C=1, B=1: Normal, Write-Back, Write-Allocate + // Not Shareable ensures strict L1 utilization. + configure_region(__ram_d1_base, __ram_d1_size, MPU_REGION_NUMBER2, + MPU_TEX_LEVEL1, MPU_REGION_FULL_ACCESS, MPU_INSTRUCTION_ACCESS_DISABLE, + MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); + + // D2 RAM Cached (Normal, WBWA) + configure_region(__ram_d2_base, __ram_d2_size, MPU_REGION_NUMBER4, + MPU_TEX_LEVEL1, MPU_REGION_FULL_ACCESS, MPU_INSTRUCTION_ACCESS_DISABLE, + MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); + + // D3 RAM Cached (Normal, WBWA) + configure_region(__ram_d3_base, __ram_d3_size, MPU_REGION_NUMBER6, + MPU_TEX_LEVEL1, MPU_REGION_FULL_ACCESS, MPU_INSTRUCTION_ACCESS_DISABLE, + MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); + } + + static void configure_region(uintptr_t base, size_t size, uint8_t region_num, + uint8_t tex, uint8_t access, uint8_t no_exec, + uint8_t shareable, uint8_t cacheable, uint8_t bufferable) { + if (size == 0) return; + + // Find smallest power of 2 >= size, starting at 32 bytes (MPU minimum) + // Enforce MPU minimum (32 bytes = 2^(4+1)) + uint8_t mpu_size = 4; + + if (size > 32) { + // Calculate ceil(log2(size)) - 1 + // __builtin_clz(x) returns leading zeros. For 32, it's 26: 31 - 26 = 5 + mpu_size = (sizeof(size) * 8 - 1) - __builtin_clz(size - 1); + } + + // Calculate SubRegion Disable (SRD) + uint32_t sub_size = (1 << (mpu_size + 1)) / 8; + // Number of subregions needed to cover 'size' + uint8_t needed_subs = (size + sub_size - 1) / sub_size; + + // We want first 'needed_subs' enabled (0), rest disabled (1) + uint8_t srd = 0xFF << needed_subs; + + MPU_Region_InitTypeDef MPU_InitStruct = {0}; + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = region_num; + MPU_InitStruct.BaseAddress = static_cast(base); // Should be uint32_t, but may be different when mocking, so this is just to make sure it accepts it + MPU_InitStruct.Size = mpu_size; + MPU_InitStruct.SubRegionDisable = srd; + MPU_InitStruct.TypeExtField = tex; + MPU_InitStruct.AccessPermission = access; + MPU_InitStruct.DisableExec = no_exec; + MPU_InitStruct.IsShareable = shareable; + MPU_InitStruct.IsCacheable = cacheable; + MPU_InitStruct.IsBufferable = bufferable; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + } +}; + +#endif // MPU_HPP diff --git a/Inc/HALAL/Models/MPUManager/MPUManager.hpp b/Inc/HALAL/Models/MPUManager/MPUManager.hpp index 9b63f46e2..fd3ba8b49 100644 --- a/Inc/HALAL/Models/MPUManager/MPUManager.hpp +++ b/Inc/HALAL/Models/MPUManager/MPUManager.hpp @@ -5,75 +5,8 @@ #define NO_CACHED_RAM_MAXIMUM_SPACE 2048 -extern unsigned long _no_cached_ram_start; - - class MPUManager{ public: - static struct config{ - bool using_cache = true; - }MPUConfig;/**< MPU configuration defined un Runes.hpp*/ - - static void start(){ - MPU_Region_InitTypeDef MPU_InitStruct = {0}; - HAL_MPU_Disable(); - - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER0; - MPU_InitStruct.BaseAddress = 0x0; - MPU_InitStruct.Size = MPU_REGION_SIZE_4GB; - MPU_InitStruct.SubRegionDisable = 0x87; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - /** Initializes and configures the Region and the memory to be protected - */ - MPU_InitStruct.Number = MPU_REGION_NUMBER1; - MPU_InitStruct.BaseAddress = 0x30000000; - MPU_InitStruct.Size = MPU_REGION_SIZE_32KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - /** Initializes and configures the Region and the memory to be protected - */ - MPU_InitStruct.Number = MPU_REGION_NUMBER2; - MPU_InitStruct.Size = MPU_REGION_SIZE_512B; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - /** Initializes and configures the Region and the memory to be protected - */ - MPU_InitStruct.Number = MPU_REGION_NUMBER3; - MPU_InitStruct.BaseAddress = 0x08000000; - MPU_InitStruct.Size = MPU_REGION_SIZE_1MB; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - - MPU_InitStruct.Number = MPU_REGION_NUMBER4; - MPU_InitStruct.BaseAddress = 0x38000000; - MPU_InitStruct.Size = MPU_REGION_SIZE_16KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - /* Enables the MPU */ - HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); - - if(MPUConfig.using_cache){ - SCB_EnableICache(); - SCB_EnableDCache(); - } - } - static void* allocate_non_cached_memory(uint32_t size){ void* buffer = (void*)((uint8_t*)no_cached_ram_start + no_cached_ram_occupied_bytes); no_cached_ram_occupied_bytes = no_cached_ram_occupied_bytes + size; diff --git a/Inc/HALAL/Services/Communication/Ethernet/Ethernet.hpp b/Inc/HALAL/Services/Communication/Ethernet/Ethernet.hpp index d58a528ad..cf194662d 100644 --- a/Inc/HALAL/Services/Communication/Ethernet/Ethernet.hpp +++ b/Inc/HALAL/Services/Communication/Ethernet/Ethernet.hpp @@ -38,7 +38,6 @@ class Ethernet{ static void update(); private: - static void mpu_start(); }; #endif diff --git a/Inc/ST-LIB.hpp b/Inc/ST-LIB.hpp index 61de272cd..a9acb61f2 100644 --- a/Inc/ST-LIB.hpp +++ b/Inc/ST-LIB.hpp @@ -83,7 +83,7 @@ template struct BuildCtx { } }; -using DomainsCtx = BuildCtx; @@ -105,6 +105,7 @@ template struct Board { constexpr std::size_t timN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); + constexpr std::size_t mpuN = domain_size(); // ... struct ConfigBundle { @@ -112,6 +113,7 @@ template struct Board { std::array tim_cfgs; std::array dout_cfgs; std::array din_cfgs; + std::array mpu_cfgs; // ... }; @@ -124,6 +126,8 @@ template struct Board { ctx.template span()), .din_cfgs = DigitalInputDomain::template build( ctx.template span()), + .mpu_cfgs = MPUDomain::template build( + ctx.template span()) // ... }; } @@ -135,6 +139,7 @@ template struct Board { constexpr std::size_t timN = domain_size(); constexpr std::size_t doutN = domain_size(); constexpr std::size_t dinN = domain_size(); + constexpr std::size_t mpuN = domain_size(); // ... GPIODomain::Init::init(cfg.gpio_cfgs); @@ -143,6 +148,7 @@ template struct Board { GPIODomain::Init::instances); DigitalInputDomain::Init::init(cfg.din_cfgs, GPIODomain::Init::instances); + MPUDomain::Init::init(); // ... } @@ -165,7 +171,12 @@ template struct Board { constexpr std::size_t idx = owner_index_of(); constexpr std::size_t N = domain_size(); - return Domain::template Init::instances[idx]; + + if constexpr (std::is_same_v) { + return Domain::template Init::instances[idx]; + } else { + return Domain::template Init::instances[idx]; + } } }; diff --git a/STM32H723ZGTX_FLASH.ld b/STM32H723ZGTX_FLASH.ld index 12b8d7793..4e1345425 100644 --- a/STM32H723ZGTX_FLASH.ld +++ b/STM32H723ZGTX_FLASH.ld @@ -35,8 +35,8 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ -_estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1); /* end of RAM */ -/* Generate a link error if heap and stack don't fit into RAM */ +_estack = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM); /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM/DTCM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ @@ -54,6 +54,22 @@ MEMORY /* Define output sections */ SECTIONS { + /* Export Memory Layout Information for MPU Configuration */ + __itcm_base = ABSOLUTE(ORIGIN(ITCMRAM)); + __itcm_size = ABSOLUTE(LENGTH(ITCMRAM)); + __dtcm_base = ABSOLUTE(ORIGIN(DTCMRAM)); + __dtcm_size = ABSOLUTE(LENGTH(DTCMRAM)); + __flash_base = ABSOLUTE(ORIGIN(FLASH)); + __flash_size = ABSOLUTE(LENGTH(FLASH)); + __ram_d1_base = ABSOLUTE(ORIGIN(RAM_D1)); + __ram_d1_size = ABSOLUTE(LENGTH(RAM_D1)); + __ram_d2_base = ABSOLUTE(ORIGIN(RAM_D2)); + __ram_d2_size = ABSOLUTE(LENGTH(RAM_D2)); + __ram_d3_base = ABSOLUTE(ORIGIN(RAM_D3)); + __ram_d3_size = ABSOLUTE(LENGTH(RAM_D3)); + __peripheral_base = 0x40000000; + __peripheral_size = 0x20000000; /* 512MB */ + /* The startup code goes first into FLASH */ .isr_vector : { @@ -118,6 +134,35 @@ SECTIONS PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH + /* MPU D1 Non-Cached Section: Placed at start of RAM_D1 for alignment */ + .mpu_ram_d1_nc : + { + . = ALIGN(32); + __mpu_d1_nc_start = ABSOLUTE(.); + + /* New MPU system buffers */ + *(.mpu_ram_d1_nc.buffer) + + /* User manual allocations via D1_NC macro */ + *(.mpu_ram_d1_nc.user) + + /* Ethernet Rx Pool */ + . = ALIGN(32); + *(.Rx_PoolSection) + } >RAM_D1 + + /* CALCULATE PADDING FOR MPU SUBREGIONS (D1) */ + _d1_size = SIZEOF(.mpu_ram_d1_nc); + /* Find next power of 2 (up to 512KB for 320KB RAM) */ + _d1_p2 = (1 << LOG2CEIL(MAX(32, _d1_size))); + /* Subregion size is RegionSize / 8 */ + _d1_sub = _d1_p2 / 8; + /* Align effective size to the subregion granularity */ + _d1_pad = (_d1_size + _d1_sub - 1) / _d1_sub * _d1_sub; + /* Advance current pointer to reserve this space */ + . = __mpu_d1_nc_start + _d1_pad; + __mpu_d1_nc_end = ABSOLUTE(.); + /* used by the startup to initialize data */ _sidata = LOADADDR(.data); @@ -128,12 +173,10 @@ SECTIONS _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ - *(.RamFunc) /* .RamFunc sections */ - *(.RamFunc*) /* .RamFunc* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end */ - } >RAM_D1 AT> FLASH + } >DTCMRAM AT> FLASH /* this needs to be the last thing in FLASH because the preceeding sections are appended after the one preceeding them @@ -160,15 +203,10 @@ SECTIONS *(.bss*) *(COMMON) - /* ETH_CODE: add placement of RX buffer. STM32H72x/H73x has small D2 RAM, so we need to put it there. - * (NOLOAD) attribute used for .bss section to avoid linker warning (.bss initialized by startup code) - */ - . = ALIGN(32); - *(.Rx_PoolSection) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; - } >RAM_D1 + } >DTCMRAM /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : @@ -179,24 +217,74 @@ SECTIONS . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); - } >RAM_D1 + } >DTCMRAM - /* ETH_CODE: add placement of DMA descriptors, rest is used by RX_POOL */ - .lwip_sec (NOLOAD) : + /* MPU D2 Non-Cached Section: Contains Ethernet Descriptors and Generic Buffers */ + .mpu_ram_d2_nc : { - . = ABSOLUTE(0x30000000); - *(.RxDecripSection) + . = ALIGN(32); + __mpu_d2_nc_start = ABSOLUTE(.); - . = ABSOLUTE(0x30000100); + /* ETH Descriptors - Must be aligned */ + *(.RxDecripSection) *(.TxDecripSection) + /* New MPU system buffers */ + *(.mpu_ram_d2_nc.buffer) + + /* User manual allocations via D2_NC macro */ + *(.mpu_ram_d2_nc.user) + } >RAM_D2 - .stlib_no_cache_ram_pool : + + /* CALCULATE PADDING FOR MPU SUBREGIONS (D2) */ + _d2_size = SIZEOF(.mpu_ram_d2_nc); + /* Find next power of 2 (up to 64KB for 32KB RAM to catch overflow logic if needed) */ + _d2_p2 = (1 << LOG2CEIL(MAX(32, _d2_size))); + _d2_sub = _d2_p2 / 8; + _d2_pad = (_d2_size + _d2_sub - 1) / _d2_sub * _d2_sub; + . = __mpu_d2_nc_start + _d2_pad; + __mpu_d2_nc_end = ABSOLUTE(.); + + /* MPU D3 Non-Cached Section */ + .mpu_ram_d3_nc : { - . = ABSOLUTE(0x38000000); - _no_cached_ram_start = .; - + . = ALIGN(32); + __mpu_d3_nc_start = ABSOLUTE(.); + + /* New MPU system buffers */ + *(.mpu_ram_d3_nc.buffer) + + /* Legacy MPUManager allocations */ + *(.mpu_ram_d3_nc.legacy) + + /* User manual allocations via D3_NC macro */ + *(.mpu_ram_d3_nc.user) + + } >RAM_D3 + + /* CALCULATE PADDING FOR MPU SUBREGIONS (D3) */ + _d3_size = SIZEOF(.mpu_ram_d3_nc); + /* Find next power of 2 (up to 32KB for 16KB RAM) */ + _d3_p2 = (1 << LOG2CEIL(MAX(32, _d3_size))); + _d3_sub = _d3_p2 / 8; + _d3_pad = (_d3_size + _d3_sub - 1) / _d3_sub * _d3_sub; + . = __mpu_d3_nc_start + _d3_pad; + __mpu_d3_nc_end = ABSOLUTE(.); + + /* Code running in ITCM RAM (0 Wait States, Instruction Bus) */ + .ram_code : + { + . = ALIGN(4); + _sram_code = .; + *(.ram_code) + *(.ram_code*) + . = ALIGN(4); + _eram_code = .; + } >ITCMRAM AT> FLASH + _siram_code = LOADADDR(.ram_code); + /* Remove information from the standard libraries */ /DISCARD/ : { @@ -206,4 +294,40 @@ SECTIONS } .ARM.attributes 0 : { *(.ARM.attributes) } + + /* MPU D1 Cached Section */ + .ram_d1 : + { + . = ALIGN(32); + + /* User manual allocations via D1_C macro */ + *(.ram_d1.user) + + /* New MPU system buffers */ + *(.ram_d1.buffer) + } >RAM_D1 + + /* MPU D2 Cached Section */ + .ram_d2 : + { + . = ALIGN(32); + + /* User manual allocations via D2_C macro */ + *(.ram_d2.user) + + /* New MPU system buffers */ + *(.ram_d2.buffer) + } >RAM_D2 + + /* MPU D3 Cached Section */ + .ram_d3 : + { + . = ALIGN(32); + + /* User manual allocations via D3_C macro */ + *(.ram_d3.user) + + /* New MPU system buffers */ + *(.ram_d3.buffer) + } >RAM_D3 } diff --git a/STM32H723ZGTX_RAM.ld b/STM32H723ZGTX_RAM.ld index 4d2e09c43..ec59ab347 100644 --- a/STM32H723ZGTX_RAM.ld +++ b/STM32H723ZGTX_RAM.ld @@ -31,6 +31,13 @@ **************************************************************************** */ +/* This linker script places code and read-only data in ITCM RAM for execution + and places initialized data in DTCM RAM. This only leaves 64kB for code, so + it could potentially overflow, if you want to host a big application, maybe + should use RAM_D1 for code as well (and either adjust MPU settings or mess + arround with the memory areas specifications, so that the code thinks RAM_D1 + is actually FLASH). */ + /* Entry Point */ ENTRY(Reset_Handler) @@ -43,25 +50,42 @@ _Min_Stack_Size = 0x400 ; /* required amount of stack */ /* Specify the memory areas */ MEMORY { - RAM_EXEC (xrw) : ORIGIN = 0x24000000, LENGTH = 320K - DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K - ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K - RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 32K - RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 16K + ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K + DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K-128K + RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 320K + RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 32K + RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 16K } /* Define output sections */ SECTIONS { - /* The startup code goes first into RAM_EXEC */ + /* Export Memory Layout Information for MPU Configuration */ + __itcm_base = ABSOLUTE(ORIGIN(ITCMRAM)); + __itcm_size = ABSOLUTE(LENGTH(ITCMRAM)); + __dtcm_base = ABSOLUTE(ORIGIN(DTCMRAM)); + __dtcm_size = ABSOLUTE(LENGTH(DTCMRAM)); + __flash_base = ABSOLUTE(ORIGIN(FLASH)); + __flash_size = ABSOLUTE(LENGTH(FLASH)); + __ram_d1_base = ABSOLUTE(ORIGIN(RAM_D1)); + __ram_d1_size = ABSOLUTE(LENGTH(RAM_D1)); + __ram_d2_base = ABSOLUTE(ORIGIN(RAM_D2)); + __ram_d2_size = ABSOLUTE(LENGTH(RAM_D2)); + __ram_d3_base = ABSOLUTE(ORIGIN(RAM_D3)); + __ram_d3_size = ABSOLUTE(LENGTH(RAM_D3)); + __peripheral_base = 0x40000000; + __peripheral_size = 0x20000000; /* 512MB */ + + /* The startup code goes into ITCM for fastest access */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); - } >RAM_EXEC + } >ITCMRAM - /* The program code and other data goes into RAM_EXEC */ + /* The program code goes into ITCM (instruction-optimized, 0 wait states) */ .text : { . = ALIGN(4); @@ -70,38 +94,36 @@ SECTIONS *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) - *(.RamFunc) /* .RamFunc sections */ - *(.RamFunc*) /* .RamFunc* sections */ KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ - } >RAM_EXEC + } >ITCMRAM - /* Constant data goes into RAM_EXEC */ + /* Constant data goes into RAM_D1 (ITCM is too small for rodata) */ .rodata : { . = ALIGN(4); *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); - } >RAM_EXEC + } >RAM_D1 - .ARM.extab (READONLY): { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM_EXEC + .ARM.extab (READONLY): { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM_D1 .ARM (READONLY): { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; - } >RAM_EXEC + } >RAM_D1 .preinit_array (READONLY): { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); - } >RAM_EXEC + } >RAM_D1 .init_array (READONLY): { @@ -109,7 +131,7 @@ SECTIONS KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); - } >RAM_EXEC + } >RAM_D1 .fini_array (READONLY): { @@ -117,12 +139,39 @@ SECTIONS KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); - } >RAM_EXEC + } >RAM_D1 + + /* MPU D1 Non-Cached Section */ + .mpu_ram_d1_nc : + { + . = ALIGN(32); + __mpu_d1_nc_start = ABSOLUTE(.); + + /* New MPU system buffers */ + *(.mpu_ram_d1_nc.buffer) + + /* User manual allocations via D1_NC macro */ + *(.mpu_ram_d1_nc.user) + + /* Ethernet Rx Pool */ + . = ALIGN(32); + *(.Rx_PoolSection) + } >RAM_D1 + + /* CALCULATE PADDING FOR MPU SUBREGIONS (D1) */ + _d1_size = SIZEOF(.mpu_ram_d1_nc); + /* Find next power of 2 */ + _d1_p2 = (1 << LOG2CEIL(MAX(32, _d1_size))); + /* Subregion size is RegionSize / 8 */ + _d1_sub = _d1_p2 / 8; + /* Align effective size to the subregion granularity */ + _d1_pad = (_d1_size + _d1_sub - 1) / _d1_sub * _d1_sub; + /* Advance current pointer to reserve this space */ + . = __mpu_d1_nc_start + _d1_pad; + __mpu_d1_nc_end = ABSOLUTE(.); - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - /* Initialized data sections goes into RAM, load LMA copy after code */ + /* Initialized data sections goes into DTCM */ .data : { . = ALIGN(4); @@ -132,7 +181,7 @@ SECTIONS . = ALIGN(4); _edata = .; /* define a global symbol at data end */ - } >DTCMRAM AT> RAM_EXEC + } >DTCMRAM /* Uninitialized data section */ . = ALIGN(4); @@ -161,6 +210,104 @@ SECTIONS . = ALIGN(8); } >DTCMRAM + /* MPU D2 Non-Cached Section */ + .mpu_ram_d2_nc : + { + . = ALIGN(32); + __mpu_d2_nc_start = ABSOLUTE(.); + + /* Ethernet descriptors */ + *(.RxDecripSection) + *(.TxDecripSection) + + /* New MPU system buffers */ + *(.mpu_ram_d2_nc.buffer) + + /* User manual allocations via D2_NC macro */ + *(.mpu_ram_d2_nc.user) + } >RAM_D2 + + /* CALCULATE PADDING FOR MPU SUBREGIONS (D2) */ + _d2_size = SIZEOF(.mpu_ram_d2_nc); + /* Find next power of 2 */ + _d2_p2 = (1 << LOG2CEIL(MAX(32, _d2_size))); + _d2_sub = _d2_p2 / 8; + _d2_pad = (_d2_size + _d2_sub - 1) / _d2_sub * _d2_sub; + . = __mpu_d2_nc_start + _d2_pad; + __mpu_d2_nc_end = ABSOLUTE(.); + + /* MPU D3 Non-Cached Section */ + .mpu_ram_d3_nc : + { + . = ALIGN(32); + __mpu_d3_nc_start = ABSOLUTE(.); + + /* New MPU system buffers */ + *(.mpu_ram_d3_nc.buffer) + + /* Legacy MPUManager allocations */ + *(.mpu_ram_d3_nc.legacy) + + /* User manual allocations via D3_NC macro */ + *(.mpu_ram_d3_nc.user) + } >RAM_D3 + + /* CALCULATE PADDING FOR MPU SUBREGIONS (D3) */ + _d3_size = SIZEOF(.mpu_ram_d3_nc); + /* Find next power of 2 */ + _d3_p2 = (1 << LOG2CEIL(MAX(32, _d3_size))); + _d3_sub = _d3_p2 / 8; + _d3_pad = (_d3_size + _d3_sub - 1) / _d3_sub * _d3_sub; + . = __mpu_d3_nc_start + _d3_pad; + __mpu_d3_nc_end = ABSOLUTE(.); + + /* Additional code in ITCM, doesn't really do much with this configuration since everything is in ITCM anyways */ + .ram_code : + { + . = ALIGN(4); + _sram_code = .; + *(.ram_code) + *(.ram_code*) + . = ALIGN(4); + _eram_code = .; + } >ITCMRAM + + /* MPU D1 Cached Section */ + .ram_d1 : + { + . = ALIGN(32); + + /* New MPU system buffers */ + *(.ram_d1.buffer) + + /* User manual allocations via D1_C macro */ + *(.ram_d1.user) + } >RAM_D1 + + /* MPU D2 Cached Section */ + .ram_d2 : + { + . = ALIGN(32); + + /* New MPU system buffers */ + *(.ram_d2.buffer) + + /* User manual allocations via D2_C macro */ + *(.ram_d2.user) + } >RAM_D2 + + /* MPU D3 Cached Section */ + .ram_d3 : + { + . = ALIGN(32); + + /* New MPU system buffers */ + *(.ram_d3.buffer) + + /* User manual allocations via D3_C macro */ + *(.ram_d3.user) + } >RAM_D3 + /* Remove information from the standard libraries */ /DISCARD/ : { diff --git a/Src/HALAL/HALAL.cpp b/Src/HALAL/HALAL.cpp index 3a309fb2d..b419bf5f5 100644 --- a/Src/HALAL/HALAL.cpp +++ b/Src/HALAL/HALAL.cpp @@ -20,7 +20,6 @@ static void common_start(UART::Peripheral &printf_peripheral) { Watchdog::check_reset_flag(); #endif - MPUManager::start(); HAL_Init(); HALconfig::system_clock(); HALconfig::peripheral_clock(); diff --git a/Src/HALAL/Models/MPUManager/MPUManager.cpp b/Src/HALAL/Models/MPUManager/MPUManager.cpp index c9ef34ca5..f3894c139 100644 --- a/Src/HALAL/Models/MPUManager/MPUManager.cpp +++ b/Src/HALAL/Models/MPUManager/MPUManager.cpp @@ -1,4 +1,7 @@ #include "HALAL/Models/MPUManager/MPUManager.hpp" -void* MPUManager::no_cached_ram_start = (void*)&_no_cached_ram_start; +__attribute__((section(".mpu_ram_d3_nc.legacy"))) alignas(32) +uint8_t mpu_manager_memory_pool[NO_CACHED_RAM_MAXIMUM_SPACE]; + +void* MPUManager::no_cached_ram_start = mpu_manager_memory_pool; uint32_t MPUManager::no_cached_ram_occupied_bytes = 0; diff --git a/Src/HALAL/Services/Communication/Ethernet/Ethernet.cpp b/Src/HALAL/Services/Communication/Ethernet/Ethernet.cpp index 65d54cbd7..effbec953 100644 --- a/Src/HALAL/Services/Communication/Ethernet/Ethernet.cpp +++ b/Src/HALAL/Services/Communication/Ethernet/Ethernet.cpp @@ -18,53 +18,6 @@ extern uint8_t IP_ADDRESS[4], NETMASK_ADDRESS[4], GATEWAY_ADDRESS[4]; bool Ethernet::is_ready = false; bool Ethernet::is_running = false; -void Ethernet::mpu_start() { - MPU_Region_InitTypeDef MPU_InitStruct = {0}; - /* Disables the MPU */ - HAL_MPU_Disable(); - /** Initializes and configures the Region and the memory to be protected - */ - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER0; - MPU_InitStruct.BaseAddress = 0x0; - MPU_InitStruct.Size = MPU_REGION_SIZE_4GB; - MPU_InitStruct.SubRegionDisable = 0x87; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - /** Initializes and configures the Region and the memory to be protected - */ - MPU_InitStruct.Number = MPU_REGION_NUMBER1; - MPU_InitStruct.BaseAddress = 0x30000000; - MPU_InitStruct.Size = MPU_REGION_SIZE_32KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - /** Initializes and configures the Region and the memory to be protected - */ - MPU_InitStruct.Number = MPU_REGION_NUMBER2; - MPU_InitStruct.Size = MPU_REGION_SIZE_512B; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - /** Initializes and configures the Region and the memory to be protected - */ - MPU_InitStruct.Number = MPU_REGION_NUMBER3; - MPU_InitStruct.BaseAddress = 0x08000000; - MPU_InitStruct.Size = MPU_REGION_SIZE_1MB; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - /* Enables the MPU */ - HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); -} void Ethernet::start(string local_mac, string local_ip, string subnet_mask, string gateway) { diff --git a/startup_stm32h723zgtx.s b/startup_stm32h723zgtx.s index 73d8bd295..819741556 100644 --- a/startup_stm32h723zgtx.s +++ b/startup_stm32h723zgtx.s @@ -79,6 +79,24 @@ LoopCopyDataInit: adds r4, r0, r3 cmp r4, r1 bcc CopyDataInit + +/* Copy the ram_code segment initializers from flash to ITCM */ + ldr r0, =_sram_code + ldr r1, =_eram_code + ldr r2, =_siram_code + movs r3, #0 + b LoopCopyRamCodeInit + +CopyRamCodeInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyRamCodeInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyRamCodeInit + /* Zero fill the bss segment. */ ldr r2, =_sbss ldr r4, =_ebss