diff --git a/targets/ChibiOS/ORGPAL_PALTHREE/CMakeLists.txt b/targets/ChibiOS/ORGPAL_PALTHREE/CMakeLists.txt index 1f87437f7f..d574e9b780 100644 --- a/targets/ChibiOS/ORGPAL_PALTHREE/CMakeLists.txt +++ b/targets/ChibiOS/ORGPAL_PALTHREE/CMakeLists.txt @@ -18,7 +18,8 @@ nf_setup_target_build( CLR_EXTRA_SOURCE_FILES # the next one is required is the target implements and it's using external memory ${CMAKE_CURRENT_SOURCE_DIR}/target_external_memory.c - + ${CMAKE_CURRENT_SOURCE_DIR}/target_mpu_config.c + BOOTER_EXTRA_COMPILE_DEFINITIONS USBH_DEBUG_MULTI_HOST=0 diff --git a/targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/main.c b/targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/main.c index f534e8dd04..fe778f3587 100644 --- a/targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/main.c +++ b/targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/main.c @@ -19,6 +19,7 @@ extern int32_t hal_lfs_config(); extern void hal_lfs_mount(); +extern void Target_ConfigMPU(); // need to declare the Receiver thread here osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); @@ -93,6 +94,9 @@ int main(void) crcStart(NULL); #endif + // MPU configuration + Target_ConfigMPU(); + // config and init external memory // this has to be called after osKernelInitialize, otherwise an hard fault will occur Target_ExternalMemoryInit(); diff --git a/targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/mcuconf.h b/targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/mcuconf.h index dea4a831d5..9fde5423b3 100644 --- a/targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/mcuconf.h +++ b/targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/mcuconf.h @@ -29,10 +29,7 @@ /* * Memory attributes settings. */ -#define STM32_NOCACHE_ENABLE TRUE -#define STM32_NOCACHE_MPU_REGION MPU_REGION_0 -#define STM32_NOCACHE_RBAR 0x20000000U -#define STM32_NOCACHE_RASR MPU_RASR_SIZE_128K +#define STM32_NOCACHE_ENABLE FALSE /* * HAL driver system settings. diff --git a/targets/ChibiOS/ORGPAL_PALTHREE/target_external_memory.c b/targets/ChibiOS/ORGPAL_PALTHREE/target_external_memory.c index fe88d1b0e9..0e8723d869 100644 --- a/targets/ChibiOS/ORGPAL_PALTHREE/target_external_memory.c +++ b/targets/ChibiOS/ORGPAL_PALTHREE/target_external_memory.c @@ -95,3 +95,46 @@ void Target_ExternalMemoryInit() fsmcSdramInit(); fsmcSdramStart(&SDRAMD, &sdram_cfg); } + +void Target_ExternalMemoryConfigMPU() +{ + // ARM: STM32F7: hard fault caused by unaligned Memory Access + // reference https://www.keil.com/support/docs/3777%20%20.htm + // SYMPTOM + // If you use an STM32F7xx microcontroller with an external SDRAM, + // the Cortex-M7 core may unexpectedly run into the hard fault handler because of unaligned access. + // This may happen for example, when the frame buffer of an LCD, a RAM filesystem or any other data is + // located into the SDRAM address range 0xC0000000 - 0xC03FFFFF (max. 4MB). + // The hard fault is executed although the bit UNALIGN_TRP (bit 3) in the CCR register is not enabled. + + // CAUSE + // In general, RAM accesses on Cortex-M7 based devices do not have to be aligned in any way. + // The Cortex-M7 core can handle unaligned accesses by hardware. + // Usually, variables should be naturally aligned because these accesses are slightly faster than unaligned + // accesses. + + // STM32F7xx devices have the external SDRAM mapped to the + // address range 0xC0000000 - 0xC03FFFFF (max. 4MB). + // According to the ARMv7-M Architecture Reference Manual chapter B3.1 (table B3-1), + // the area 0xC0000000-0xDFFFFFFF (32MB) is specified as Device Memory Type. + // According to chapter A3.2.1, all accesses to Device Memory Types must be naturally aligned. + // If they are not, a hard fault will execute no matter if the bit UNALIGN_TRP (bit 3) in the CCR register is + // enabled or not. + + MPU_Region_InitTypeDef MPU_InitStruct; + + // Configure the MPU attributes for SDRAM + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.BaseAddress = 0xD0000000; + MPU_InitStruct.Size = MPU_REGION_SIZE_8MB; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.SubRegionDisable = 0x00; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); +} diff --git a/targets/ChibiOS/ORGPAL_PALTHREE/target_mpu_config.c b/targets/ChibiOS/ORGPAL_PALTHREE/target_mpu_config.c new file mode 100644 index 0000000000..21872e3174 --- /dev/null +++ b/targets/ChibiOS/ORGPAL_PALTHREE/target_mpu_config.c @@ -0,0 +1,40 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +extern void Target_ExternalMemoryConfigMPU(); + +void Target_ConfigNonCacheableMemory() +{ + // region + MPU->RNR = ((uint32_t)MPU_REGION_1); + + // base address + MPU->RBAR = ((uint32_t)0x20000000U); + + // size and other configs + MPU->RASR = + ((uint32_t)MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | MPU_RASR_ATTR_S | MPU_RASR_SIZE_128K | + MPU_RASR_ENABLE); +} + +void Target_ConfigMPU() +{ + // disable MPU + HAL_MPU_Disable(); + + // config MPU for external memory + Target_ExternalMemoryConfigMPU(); + + // config MPU for non cacheable memory + Target_ConfigNonCacheableMemory(); + + // enable MPU + HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); +} diff --git a/targets/ChibiOS/ORGPAL_PALX/CMakeLists.txt b/targets/ChibiOS/ORGPAL_PALX/CMakeLists.txt index a8bea0d2c1..27dc16de48 100644 --- a/targets/ChibiOS/ORGPAL_PALX/CMakeLists.txt +++ b/targets/ChibiOS/ORGPAL_PALX/CMakeLists.txt @@ -18,6 +18,7 @@ nf_setup_target_build( CLR_EXTRA_SOURCE_FILES # the next one is required is the target implements and it's using external memory ${CMAKE_CURRENT_SOURCE_DIR}/target_external_memory.c + ${CMAKE_CURRENT_SOURCE_DIR}/target_mpu_config.c BOOTER_EXTRA_COMPILE_DEFINITIONS -DUSBH_DEBUG_MULTI_HOST=0 diff --git a/targets/ChibiOS/ORGPAL_PALX/nanoCLR/main.c b/targets/ChibiOS/ORGPAL_PALX/nanoCLR/main.c index ecf31788e8..245c0a1660 100644 --- a/targets/ChibiOS/ORGPAL_PALX/nanoCLR/main.c +++ b/targets/ChibiOS/ORGPAL_PALX/nanoCLR/main.c @@ -19,6 +19,7 @@ extern int32_t hal_lfs_config(); extern void hal_lfs_mount(); +extern void Target_ConfigMPU(); // need to declare the Receiver thread here osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread"); @@ -93,6 +94,9 @@ int main(void) crcStart(NULL); #endif + // MPU configuration + Target_ConfigMPU(); + // config and init external memory // this has to be called after osKernelInitialize, otherwise an hard fault will occur Target_ExternalMemoryInit(); diff --git a/targets/ChibiOS/ORGPAL_PALX/nanoCLR/mcuconf.h b/targets/ChibiOS/ORGPAL_PALX/nanoCLR/mcuconf.h index a786fb173c..bfbf3f5196 100644 --- a/targets/ChibiOS/ORGPAL_PALX/nanoCLR/mcuconf.h +++ b/targets/ChibiOS/ORGPAL_PALX/nanoCLR/mcuconf.h @@ -27,10 +27,7 @@ /* * Memory attributes settings. */ -#define STM32_NOCACHE_ENABLE TRUE -#define STM32_NOCACHE_MPU_REGION MPU_REGION_0 -#define STM32_NOCACHE_RBAR 0x20000000U -#define STM32_NOCACHE_RASR MPU_RASR_SIZE_128K +#define STM32_NOCACHE_ENABLE FALSE /* * HAL driver system settings. diff --git a/targets/ChibiOS/ORGPAL_PALX/target_external_memory.c b/targets/ChibiOS/ORGPAL_PALX/target_external_memory.c index 0e4f9055c4..0e8723d869 100644 --- a/targets/ChibiOS/ORGPAL_PALX/target_external_memory.c +++ b/targets/ChibiOS/ORGPAL_PALX/target_external_memory.c @@ -69,8 +69,6 @@ #define SDRAM_SIZE (8 * 1024 * 1024) #define SDRAM_START ((void *)FSMC_Bank6_MAP_BASE) -void SetupDeviceMemoryToEliminateUnalignedAccess(); - // SDRAM driver configuration structure. static const SDRAMConfig sdram_cfg = { .sdcr = (uint32_t)FMC_ColumnBits_Number_8b | FMC_RowBits_Number_12b | FMC_SDMemory_Width_16b | @@ -94,12 +92,11 @@ static const SDRAMConfig sdram_cfg = { void Target_ExternalMemoryInit() { - SetupDeviceMemoryToEliminateUnalignedAccess(); fsmcSdramInit(); fsmcSdramStart(&SDRAMD, &sdram_cfg); } -void SetupDeviceMemoryToEliminateUnalignedAccess() +void Target_ExternalMemoryConfigMPU() { // ARM: STM32F7: hard fault caused by unaligned Memory Access // reference https://www.keil.com/support/docs/3777%20%20.htm @@ -124,37 +121,20 @@ void SetupDeviceMemoryToEliminateUnalignedAccess() // If they are not, a hard fault will execute no matter if the bit UNALIGN_TRP (bit 3) in the CCR register is // enabled or not. - // Solution recommended by KEIL - -#define MPU_REGION_ENABLE ((uint8_t)0x01U) -#define MPU_REGION_SIZE_8MB ((uint8_t)0x16U) -#define MPU_REGION_FULL_ACCESS ((uint8_t)0x03U) -#define MPU_ACCESS_NOT_BUFFERABLE ((uint8_t)0x00U) -#define MPU_ACCESS_NOT_CACHEABLE ((uint8_t)0x00U) -#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U) -#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U) -#define MPU_REGION_NUMBER0 ((uint8_t)0x00U) -#define MPU_TEX_LEVEL1 ((uint8_t)0x01U) -#define MPU_INSTRUCTION_ACCESS_DISABLE ((uint8_t)0x01U) -#define MPU_PRIVILEGED_DEFAULT ((uint32_t)0x00000004U) - - // Disable the MPU - __DMB(); - SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; - MPU->CTRL = 0; - - // Configure the region - MPU->RNR = MPU_REGION_NUMBER0; - MPU->RBAR = 0xC0000000; - MPU->RASR = (MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos) | (MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos) | - (MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos) | (MPU_ACCESS_NOT_SHAREABLE << MPU_RASR_S_Pos) | - (MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos) | (MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos) | - (0x00 << MPU_RASR_SRD_Pos) | (MPU_REGION_SIZE_8MB << MPU_RASR_SIZE_Pos) | - (MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos); - - // Enable the MPU - MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk; - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; - __DSB(); - __ISB(); + MPU_Region_InitTypeDef MPU_InitStruct; + + // Configure the MPU attributes for SDRAM + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.BaseAddress = 0xD0000000; + MPU_InitStruct.Size = MPU_REGION_SIZE_8MB; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.SubRegionDisable = 0x00; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); } diff --git a/targets/ChibiOS/ORGPAL_PALX/target_mpu_config.c b/targets/ChibiOS/ORGPAL_PALX/target_mpu_config.c new file mode 100644 index 0000000000..21872e3174 --- /dev/null +++ b/targets/ChibiOS/ORGPAL_PALX/target_mpu_config.c @@ -0,0 +1,40 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include +#include + +extern void Target_ExternalMemoryConfigMPU(); + +void Target_ConfigNonCacheableMemory() +{ + // region + MPU->RNR = ((uint32_t)MPU_REGION_1); + + // base address + MPU->RBAR = ((uint32_t)0x20000000U); + + // size and other configs + MPU->RASR = + ((uint32_t)MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | MPU_RASR_ATTR_S | MPU_RASR_SIZE_128K | + MPU_RASR_ENABLE); +} + +void Target_ConfigMPU() +{ + // disable MPU + HAL_MPU_Disable(); + + // config MPU for external memory + Target_ExternalMemoryConfigMPU(); + + // config MPU for non cacheable memory + Target_ConfigNonCacheableMemory(); + + // enable MPU + HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); +} diff --git a/targets/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c b/targets/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c index cfb4185af0..61206a3b02 100644 --- a/targets/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c +++ b/targets/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c @@ -69,7 +69,7 @@ #define SDRAM_SIZE (16 * 1024 * 1024) #define SDRAM_START ((void *)FSMC_Bank5_MAP_BASE) -void SetupDeviceMemoryToEliminateUnalignedAccess(); +void Target_ExternalMemoryConfigMPU(); // SDRAM driver configuration structure. static const SDRAMConfig sdram_cfg = { @@ -94,12 +94,12 @@ static const SDRAMConfig sdram_cfg = { void Target_ExternalMemoryInit() { - SetupDeviceMemoryToEliminateUnalignedAccess(); + Target_ExternalMemoryConfigMPU(); fsmcSdramInit(); fsmcSdramStart(&SDRAMD, &sdram_cfg); } -void SetupDeviceMemoryToEliminateUnalignedAccess() +void Target_ExternalMemoryConfigMPU() { // ARM: STM32F7: hard fault caused by unaligned Memory Access // reference https://www.keil.com/support/docs/3777%20%20.htm @@ -124,37 +124,20 @@ void SetupDeviceMemoryToEliminateUnalignedAccess() // If they are not, a hard fault will execute no matter if the bit UNALIGN_TRP (bit 3) in the CCR register is // enabled or not. - // Solution recommended by KEIL - -#define MPU_REGION_ENABLE ((uint8_t)0x01U) -#define MPU_REGION_SIZE_4MB ((uint8_t)0x15) -#define MPU_REGION_FULL_ACCESS ((uint8_t)0x03U) -#define MPU_ACCESS_NOT_BUFFERABLE ((uint8_t)0x00U) -#define MPU_ACCESS_NOT_CACHEABLE ((uint8_t)0x00U) -#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U) -#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U) -#define MPU_REGION_NUMBER0 ((uint8_t)0x00U) -#define MPU_TEX_LEVEL1 ((uint8_t)0x01U) -#define MPU_INSTRUCTION_ACCESS_DISABLE ((uint8_t)0x01U) -#define MPU_PRIVILEGED_DEFAULT ((uint32_t)0x00000004U) - - // Disable the MPU - __DMB(); - SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; - MPU->CTRL = 0; - - // Configure the region - MPU->RNR = MPU_REGION_NUMBER0; - MPU->RBAR = 0xC0000000; - MPU->RASR = (MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos) | (MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos) | - (MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos) | (MPU_ACCESS_NOT_SHAREABLE << MPU_RASR_S_Pos) | - (MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos) | (MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos) | - (0x00 << MPU_RASR_SRD_Pos) | (MPU_REGION_SIZE_4MB << MPU_RASR_SIZE_Pos) | - (MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos); - - // Enable the MPU - MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk; - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; - __DSB(); - __ISB(); + MPU_Region_InitTypeDef MPU_InitStruct; + + // Configure the MPU attributes for SDRAM + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.BaseAddress = 0xC0000000; + MPU_InitStruct.Size = MPU_REGION_SIZE_8MB; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.SubRegionDisable = 0x00; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); }