diff --git a/src/fw/drivers/mpu.c b/src/fw/drivers/mpu.c index 694c79ba7..25fcd1320 100644 --- a/src/fw/drivers/mpu.c +++ b/src/fw/drivers/mpu.c @@ -124,7 +124,11 @@ void mpu_enable(void) { s_cache_settings[MpuCachePolicy_WriteBackNoWriteAllocate]); #endif +#ifdef MICRO_FAMILY_SF32LB52 + ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); +#else ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk); +#endif } void mpu_disable(void) { @@ -269,18 +273,16 @@ void mpu_set_task_configurable_regions(MemoryRegion_t *memory_regions, // If not region defined, use unused if (mpu_region == NULL) { mpu_region = &unused_region; + base_reg = 0; attr_reg = 0; // Has a 0 in the enable bit, so this region won't be enabled. } else { // Make sure that the region numbers passed in jive with the configurable region numbers. PBL_ASSERTN(mpu_region->region_num == region_num); - // Our FreeRTOS port makes the assumption that the ulParameters field contains exactly what - // should be placed into the MPU_RASR register. It will figure out the MPU_RBAR from the - // pvBaseAddress field. mpu_get_register_settings(mpu_region, &base_reg, &attr_reg); } memory_regions[region_idx] = (MemoryRegion_t) { - .pvBaseAddress = (void *)mpu_region->base_address, + .pvBaseAddress = (void *)(uintptr_t)base_reg, .ulLengthInBytes = mpu_region->size, .ulParameters = attr_reg, }; diff --git a/src/fw/kernel/pebble_tasks.c b/src/fw/kernel/pebble_tasks.c index 525b34e39..02ed98c71 100644 --- a/src/fw/kernel/pebble_tasks.c +++ b/src/fw/kernel/pebble_tasks.c @@ -13,6 +13,7 @@ #include "util/size.h" #include "FreeRTOS.h" +#include "portmacro.h" #include "task.h" #include "queue.h" @@ -197,14 +198,22 @@ void pebble_task_create(PebbleTask pebble_task, TaskParameters_t *task_params, WTF; } + app_region.region_num = portFIRST_CONFIGURABLE_REGION; + worker_region.region_num = portFIRST_CONFIGURABLE_REGION + 1; + + MpuRegion stack_guard_copy; + const MpuRegion *stack_guard_ptr = NULL; + if (stack_guard_region != NULL) { + stack_guard_copy = *stack_guard_region; + stack_guard_copy.region_num = portFIRST_CONFIGURABLE_REGION + 2; + stack_guard_ptr = &stack_guard_copy; + } + const MpuRegion *region_ptrs[portNUM_CONFIGURABLE_REGIONS] = { - // FIXME(SF32LB52): Not supported on ARMv8 MPU yet -#ifndef MICRO_FAMILY_SF32LB52 &app_region, &worker_region, - stack_guard_region, + stack_guard_ptr, NULL -#endif }; mpu_set_task_configurable_regions(task_params->xRegions, region_ptrs); @@ -232,6 +241,8 @@ void pebble_task_configure_idle_task(void) { false /* allow_user_access */); mpu_init_region_from_region(&worker_region, memory_layout_get_worker_region(), false /* allow_user_access */); + app_region.region_num = portFIRST_CONFIGURABLE_REGION; + worker_region.region_num = portFIRST_CONFIGURABLE_REGION + 1; const MpuRegion *region_ptrs[portNUM_CONFIGURABLE_REGIONS] = { &app_region, &worker_region, diff --git a/src/fw/wscript b/src/fw/wscript index 7162b8487..9ae719c68 100644 --- a/src/fw/wscript +++ b/src/fw/wscript @@ -264,17 +264,13 @@ def _generate_memory_layout(bld): app_ram_size_3x = APP_RAM_SIZES['basalt'] app_ram_size_4x = APP_RAM_SIZES['emery'] # We have 512K of SRAM, last 1K reserved for LCPU IPC - # FIXME(SF32LB52): due to MPU find_subregions_for_region assuming - # ARMv7 subregion limitations, we need to reserve 32K! - total_ram = (0x20000000, (512 - 32) * 1024) + total_ram = (0x20000000, (512 - 1) * 1024) elif bld.is_getafix(): app_ram_size_2x = APP_UNSUPPORTED app_ram_size_3x = APP_RAM_SIZES['chalk'] app_ram_size_4x = APP_RAM_SIZES['gabbro'] # We have 512K of SRAM, last 1K reserved for LCPU IPC - # FIXME(SF32LB52): due to MPU find_subregions_for_region assuming - # ARMv7 subregion limitations, we need to reserve 32K! - total_ram = (0x20000000, (512 - 32) * 1024) + total_ram = (0x20000000, (512 - 1) * 1024) else: bld.fatal("No set of supported SDK platforms defined for this board") @@ -320,18 +316,26 @@ def _generate_memory_layout(bld): FLASH_SIZE=flash_size, BOOTLOADER_SYMBOLS=bootloader_symbol_definitions) - app_mpu_region = tools.mpu_calc.find_subregions_for_region(app_ram[0], app_ram[1]) - worker_mpu_region = tools.mpu_calc.find_subregions_for_region(worker_ram[0], worker_ram[1]) + if bld.env.MICRO_FAMILY == 'SF32LB52': + app_mpu_region = tools.mpu_calc.find_region_for_armv8(app_ram[0], app_ram[1]) + worker_mpu_region = tools.mpu_calc.find_region_for_armv8(worker_ram[0], worker_ram[1]) + app_disabled_sub = "0" + worker_disabled_sub = "0" + else: + app_mpu_region = tools.mpu_calc.find_subregions_for_region(app_ram[0], app_ram[1]) + worker_mpu_region = tools.mpu_calc.find_subregions_for_region(worker_ram[0], worker_ram[1]) + app_disabled_sub = "0b{:08b}".format(app_mpu_region.disabled_subregion) + worker_disabled_sub = " 0b{:08b}".format(worker_mpu_region.disabled_subregion) bld(features='subst', source=bld.path.find_node('kernel/mpu_regions.template.h'), target=bld.path.get_bld().make_node('kernel/mpu_regions.auto.h'), APP_BASE_ADDRESS="0x{:x}".format(app_mpu_region.address), APP_SIZE="0x{:x}".format(app_mpu_region.size), - APP_DISABLED_SUBREGIONS="0b{:08b}".format(app_mpu_region.disabled_subregion), + APP_DISABLED_SUBREGIONS=app_disabled_sub, WORKER_BASE_ADDRESS="0x{:x}".format(worker_mpu_region.address), WORKER_SIZE="0x{:x}".format(worker_mpu_region.size), - WORKER_DISABLED_SUBREGIONS=" 0b{:08b}".format(worker_mpu_region.disabled_subregion)) + WORKER_DISABLED_SUBREGIONS=worker_disabled_sub) bld(features='subst', source=bld.path.find_node('process_management/sdk_memory_limits.template.h'), diff --git a/third_party/freertos/wscript b/third_party/freertos/wscript index ee9e5a6f7..4ae63ea82 100644 --- a/third_party/freertos/wscript +++ b/third_party/freertos/wscript @@ -26,11 +26,9 @@ def build(bld): for d in freertos_source_paths], []) freertos_defines = [] - # FIXME(SF32LB52): Add valid regions once MPU can be used - # This currently results in 0 regions! if bld.env.MICRO_FAMILY == 'SF32LB52': freertos_defines += [ - 'FREERTOS_FIRST_MPU_REGION=8', + 'FREERTOS_FIRST_MPU_REGION=4', 'FREERTOS_LAST_MPU_REGION=7', ] diff --git a/tools/mpu_calc.py b/tools/mpu_calc.py index e60d5a671..c0be7579f 100644 --- a/tools/mpu_calc.py +++ b/tools/mpu_calc.py @@ -91,6 +91,21 @@ def find_subregions_for_region(address, size): raise Exception("No solution found") +def find_region_for_armv8(address, size): + """Find MPU region for ARMv8-M (no subregions, arbitrary 32-byte-aligned size). + + ARMv8-M MPU supports regions of any size aligned to 32 bytes. + Returns MpuRegion(address, size, 0) with disabled_subregion=0 (unused on ARMv8). + """ + if address % 32 != 0: + raise Exception("Address must be 32-byte aligned for ARMv8-M MPU") + if size % 32 != 0: + raise Exception("Size must be 32-byte aligned for ARMv8-M MPU") + if size < MIN_REGION_SIZE: + raise Exception("Size must be at least 32 bytes") + return MpuRegion(address=address, size=size, disabled_subregion=0) + + if __name__ == "__main__": import doctest