Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework MPU config for unaligned access to external memory #3044

Merged
merged 1 commit into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion targets/ChibiOS/ORGPAL_PALTHREE/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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();
Expand Down
5 changes: 1 addition & 4 deletions targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/mcuconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion targets/ChibiOS/ORGPAL_PALTHREE/stm32f7xx_hal_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extern "C"
// #define HAL_NAND_MODULE_ENABLED
// #define HAL_NOR_MODULE_ENABLED
// #define HAL_SRAM_MODULE_ENABLED
// #define HAL_SDRAM_MODULE_ENABLED
#define HAL_SDRAM_MODULE_ENABLED
// #define HAL_HASH_MODULE_ENABLED
// #define HAL_GPIO_MODULE_ENABLED
// #define HAL_I2C_MODULE_ENABLED
Expand Down
46 changes: 45 additions & 1 deletion targets/ChibiOS/ORGPAL_PALTHREE/target_external_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

#include <ch.h>
#include "hal.h"
#include "fsmc_sdram_lld.h"
#include <fsmc_sdram_lld.h>
#include <stm32f7xx_hal.h>

// SDRAM Mode definition register defines
#define FMC_SDCMR_MRD_BURST_LENGTH_1 ((uint16_t)0x0000)
Expand Down Expand Up @@ -95,3 +96,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_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);
josesimoes marked this conversation as resolved.
Show resolved Hide resolved
}
josesimoes marked this conversation as resolved.
Show resolved Hide resolved
44 changes: 44 additions & 0 deletions targets/ChibiOS/ORGPAL_PALTHREE/target_mpu_config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//

#include <ch.h>
#include <hal.h>
#include <stm32_registry.h>
#include <hal_nf_community.h>

josesimoes marked this conversation as resolved.
Show resolved Hide resolved
extern void Target_ExternalMemoryConfigMPU();

// SRAM1 base address
#define SRAM1_SIZE_128K (1UL << 16) // 2^17 bytes
#define MPU_REGION_SRAM1 MPU_REGION_1
josesimoes marked this conversation as resolved.
Show resolved Hide resolved

void Target_ConfigNonCacheableMemory()
{
// region
MPU->RNR = MPU_REGION_SRAM1;

// base address
MPU->RBAR = SRAM1_BASE;

// 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);
}
josesimoes marked this conversation as resolved.
Show resolved Hide resolved

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);
}
josesimoes marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions targets/ChibiOS/ORGPAL_PALX/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions targets/ChibiOS/ORGPAL_PALX/nanoCLR/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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();
Expand Down
5 changes: 1 addition & 4 deletions targets/ChibiOS/ORGPAL_PALX/nanoCLR/mcuconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion targets/ChibiOS/ORGPAL_PALX/stm32f7xx_hal_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ extern "C"
// #define HAL_FLASH_MODULE_ENABLED
// #define HAL_NAND_MODULE_ENABLED
// #define HAL_NOR_MODULE_ENABLED
// #define HAL_SRAM_MODULE_ENABLED
#define HAL_SDRAM_MODULE_ENABLED
// #define HAL_SDRAM_MODULE_ENABLED
// #define HAL_HASH_MODULE_ENABLED
// #define HAL_GPIO_MODULE_ENABLED
Expand Down
59 changes: 20 additions & 39 deletions targets/ChibiOS/ORGPAL_PALX/target_external_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
//

#include <ch.h>
#include "hal.h"
#include "fsmc_sdram_lld.h"
#include <hal.h>
#include <fsmc_sdram_lld.h>
#include <stm32f7xx_hal.h>

// SDRAM Mode definition register defines
#define FMC_SDCMR_MRD_BURST_LENGTH_1 ((uint16_t)0x0000)
Expand Down Expand Up @@ -69,8 +70,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 |
Expand All @@ -94,12 +93,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
Expand All @@ -124,37 +122,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_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);
}
44 changes: 44 additions & 0 deletions targets/ChibiOS/ORGPAL_PALX/target_mpu_config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//

#include <ch.h>
#include <hal.h>
#include <stm32_registry.h>
#include <hal_nf_community.h>

extern void Target_ExternalMemoryConfigMPU();

// SRAM1 base address
#define SRAM1_SIZE_128K (1UL << 16) // 2^17 bytes
#define MPU_REGION_SRAM1 MPU_REGION_1

void Target_ConfigNonCacheableMemory()
{
// region
MPU->RNR = MPU_REGION_SRAM1;

// base address
MPU->RBAR = SRAM1_BASE;

// 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);
}
2 changes: 1 addition & 1 deletion targets/ChibiOS/ST_STM32F769I_DISCOVERY/CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"RTOS": "ChibiOS",
"TARGET_SERIES": "STM32F7xx",
"CHIBIOS_CONTRIB_REQUIRED": "OFF",
"STM32_CUBE_PACKAGE_REQUIRED": "OFF",
"STM32_CUBE_PACKAGE_REQUIRED": "ON",
"SUPPORT_ANY_BASE_CONVERSION": "ON",
"NF_FEATURE_DEBUGGER": "ON",
"NF_FEATURE_RTC": "ON",
Expand Down
23 changes: 23 additions & 0 deletions targets/ChibiOS/ST_STM32F769I_DISCOVERY/stm32f7xx_hal_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,26 @@ extern "C"
#endif

#define HAL_DMA_MODULE_ENABLED
#define HAL_SDRAM_MODULE_ENABLED
#define HAL_QSPI_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
josesimoes marked this conversation as resolved.
Show resolved Hide resolved

// ########################### System Configuration #########################
// This is the HAL system configuration section

// Value of VDD in mv
#define VDD_VALUE (3300U)
// tick interrupt priority
#define TICK_INT_PRIORITY (0x0FU)
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
// To enable instruction cache and prefetch
#define ART_ACCELERATOR_ENABLE 1U

#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */
#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */
#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */

#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32f7xx_hal_rcc.h"
Expand All @@ -33,6 +48,14 @@ extern "C"
#include "stm32f7xx_hal_qspi.h"
#endif /* HAL_QSPI_MODULE_ENABLED */

#ifdef HAL_SDRAM_MODULE_ENABLED
#include "stm32f7xx_hal_sdram.h"
#endif /* HAL_SDRAM_MODULE_ENABLED */

#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32f7xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */

#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
Expand Down
Loading