Skip to content

Commit ec25d8a

Browse files
committed
Rework MPU config for unaligned access to external memory
- Add MPU config to ORGPAL3 and ORGPALX to allow unaligned access to external memory. - Remove MPU config for non cached memory in ChibiOS mcu config for ORGPAL3 and ORGPALX. Now are in Target_ConfigNonCacheableMemory(). - Rework call to MPU config in ORGPAL3 and ORGPALX. - Migrate ST_STM32F769I_DISCOVERY MPU config to use ST HAL API.
1 parent 9498e56 commit ec25d8a

File tree

11 files changed

+172
-82
lines changed

11 files changed

+172
-82
lines changed

targets/ChibiOS/ORGPAL_PALTHREE/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ nf_setup_target_build(
1818
CLR_EXTRA_SOURCE_FILES
1919
# the next one is required is the target implements and it's using external memory
2020
${CMAKE_CURRENT_SOURCE_DIR}/target_external_memory.c
21-
21+
${CMAKE_CURRENT_SOURCE_DIR}/target_mpu_config.c
22+
2223
BOOTER_EXTRA_COMPILE_DEFINITIONS
2324
USBH_DEBUG_MULTI_HOST=0
2425

targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
extern int32_t hal_lfs_config();
2121
extern void hal_lfs_mount();
22+
extern void Target_ConfigMPU();
2223

2324
// need to declare the Receiver thread here
2425
osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread");
@@ -93,6 +94,9 @@ int main(void)
9394
crcStart(NULL);
9495
#endif
9596

97+
// MPU configuration
98+
Target_ConfigMPU();
99+
96100
// config and init external memory
97101
// this has to be called after osKernelInitialize, otherwise an hard fault will occur
98102
Target_ExternalMemoryInit();

targets/ChibiOS/ORGPAL_PALTHREE/nanoCLR/mcuconf.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@
2929
/*
3030
* Memory attributes settings.
3131
*/
32-
#define STM32_NOCACHE_ENABLE TRUE
33-
#define STM32_NOCACHE_MPU_REGION MPU_REGION_0
34-
#define STM32_NOCACHE_RBAR 0x20000000U
35-
#define STM32_NOCACHE_RASR MPU_RASR_SIZE_128K
32+
#define STM32_NOCACHE_ENABLE FALSE
3633

3734
/*
3835
* HAL driver system settings.

targets/ChibiOS/ORGPAL_PALTHREE/target_external_memory.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,46 @@ void Target_ExternalMemoryInit()
9595
fsmcSdramInit();
9696
fsmcSdramStart(&SDRAMD, &sdram_cfg);
9797
}
98+
99+
void Target_ExternalMemoryConfigMPU()
100+
{
101+
// ARM: STM32F7: hard fault caused by unaligned Memory Access
102+
// reference https://www.keil.com/support/docs/3777%20%20.htm
103+
// SYMPTOM
104+
// If you use an STM32F7xx microcontroller with an external SDRAM,
105+
// the Cortex-M7 core may unexpectedly run into the hard fault handler because of unaligned access.
106+
// This may happen for example, when the frame buffer of an LCD, a RAM filesystem or any other data is
107+
// located into the SDRAM address range 0xC0000000 - 0xC03FFFFF (max. 4MB).
108+
// The hard fault is executed although the bit UNALIGN_TRP (bit 3) in the CCR register is not enabled.
109+
110+
// CAUSE
111+
// In general, RAM accesses on Cortex-M7 based devices do not have to be aligned in any way.
112+
// The Cortex-M7 core can handle unaligned accesses by hardware.
113+
// Usually, variables should be naturally aligned because these accesses are slightly faster than unaligned
114+
// accesses.
115+
116+
// STM32F7xx devices have the external SDRAM mapped to the
117+
// address range 0xC0000000 - 0xC03FFFFF (max. 4MB).
118+
// According to the ARMv7-M Architecture Reference Manual chapter B3.1 (table B3-1),
119+
// the area 0xC0000000-0xDFFFFFFF (32MB) is specified as Device Memory Type.
120+
// According to chapter A3.2.1, all accesses to Device Memory Types must be naturally aligned.
121+
// If they are not, a hard fault will execute no matter if the bit UNALIGN_TRP (bit 3) in the CCR register is
122+
// enabled or not.
123+
124+
MPU_Region_InitTypeDef MPU_InitStruct;
125+
126+
// Configure the MPU attributes for SDRAM
127+
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
128+
MPU_InitStruct.BaseAddress = 0xD0000000;
129+
MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
130+
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
131+
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
132+
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
133+
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
134+
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
135+
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
136+
MPU_InitStruct.SubRegionDisable = 0x00;
137+
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
138+
139+
HAL_MPU_ConfigRegion(&MPU_InitStruct);
140+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// See LICENSE file in the project root for full license information.
4+
//
5+
6+
#include <ch.h>
7+
#include <hal.h>
8+
#include <stm32_registry.h>
9+
#include <hal_nf_community.h>
10+
11+
extern void Target_ExternalMemoryConfigMPU();
12+
13+
void Target_ConfigNonCacheableMemory()
14+
{
15+
// region
16+
MPU->RNR = ((uint32_t)MPU_REGION_1);
17+
18+
// base address
19+
MPU->RBAR = ((uint32_t)0x20000000U);
20+
21+
// size and other configs
22+
MPU->RASR =
23+
((uint32_t)MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | MPU_RASR_ATTR_S | MPU_RASR_SIZE_128K |
24+
MPU_RASR_ENABLE);
25+
}
26+
27+
void Target_ConfigMPU()
28+
{
29+
// disable MPU
30+
HAL_MPU_Disable();
31+
32+
// config MPU for external memory
33+
Target_ExternalMemoryConfigMPU();
34+
35+
// config MPU for non cacheable memory
36+
Target_ConfigNonCacheableMemory();
37+
38+
// enable MPU
39+
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
40+
}

targets/ChibiOS/ORGPAL_PALX/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ nf_setup_target_build(
1818
CLR_EXTRA_SOURCE_FILES
1919
# the next one is required is the target implements and it's using external memory
2020
${CMAKE_CURRENT_SOURCE_DIR}/target_external_memory.c
21+
${CMAKE_CURRENT_SOURCE_DIR}/target_mpu_config.c
2122

2223
BOOTER_EXTRA_COMPILE_DEFINITIONS
2324
-DUSBH_DEBUG_MULTI_HOST=0

targets/ChibiOS/ORGPAL_PALX/nanoCLR/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
extern int32_t hal_lfs_config();
2121
extern void hal_lfs_mount();
22+
extern void Target_ConfigMPU();
2223

2324
// need to declare the Receiver thread here
2425
osThreadDef(ReceiverThread, osPriorityHigh, 2048, "ReceiverThread");
@@ -93,6 +94,9 @@ int main(void)
9394
crcStart(NULL);
9495
#endif
9596

97+
// MPU configuration
98+
Target_ConfigMPU();
99+
96100
// config and init external memory
97101
// this has to be called after osKernelInitialize, otherwise an hard fault will occur
98102
Target_ExternalMemoryInit();

targets/ChibiOS/ORGPAL_PALX/nanoCLR/mcuconf.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@
2727
/*
2828
* Memory attributes settings.
2929
*/
30-
#define STM32_NOCACHE_ENABLE TRUE
31-
#define STM32_NOCACHE_MPU_REGION MPU_REGION_0
32-
#define STM32_NOCACHE_RBAR 0x20000000U
33-
#define STM32_NOCACHE_RASR MPU_RASR_SIZE_128K
30+
#define STM32_NOCACHE_ENABLE FALSE
3431

3532
/*
3633
* HAL driver system settings.

targets/ChibiOS/ORGPAL_PALX/target_external_memory.c

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@
6969
#define SDRAM_SIZE (8 * 1024 * 1024)
7070
#define SDRAM_START ((void *)FSMC_Bank6_MAP_BASE)
7171

72-
void SetupDeviceMemoryToEliminateUnalignedAccess();
73-
7472
// SDRAM driver configuration structure.
7573
static const SDRAMConfig sdram_cfg = {
7674
.sdcr = (uint32_t)FMC_ColumnBits_Number_8b | FMC_RowBits_Number_12b | FMC_SDMemory_Width_16b |
@@ -94,12 +92,11 @@ static const SDRAMConfig sdram_cfg = {
9492

9593
void Target_ExternalMemoryInit()
9694
{
97-
SetupDeviceMemoryToEliminateUnalignedAccess();
9895
fsmcSdramInit();
9996
fsmcSdramStart(&SDRAMD, &sdram_cfg);
10097
}
10198

102-
void SetupDeviceMemoryToEliminateUnalignedAccess()
99+
void Target_ExternalMemoryConfigMPU()
103100
{
104101
// ARM: STM32F7: hard fault caused by unaligned Memory Access
105102
// reference https://www.keil.com/support/docs/3777%20%20.htm
@@ -124,37 +121,20 @@ void SetupDeviceMemoryToEliminateUnalignedAccess()
124121
// If they are not, a hard fault will execute no matter if the bit UNALIGN_TRP (bit 3) in the CCR register is
125122
// enabled or not.
126123

127-
// Solution recommended by KEIL
128-
129-
#define MPU_REGION_ENABLE ((uint8_t)0x01U)
130-
#define MPU_REGION_SIZE_8MB ((uint8_t)0x16U)
131-
#define MPU_REGION_FULL_ACCESS ((uint8_t)0x03U)
132-
#define MPU_ACCESS_NOT_BUFFERABLE ((uint8_t)0x00U)
133-
#define MPU_ACCESS_NOT_CACHEABLE ((uint8_t)0x00U)
134-
#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U)
135-
#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U)
136-
#define MPU_REGION_NUMBER0 ((uint8_t)0x00U)
137-
#define MPU_TEX_LEVEL1 ((uint8_t)0x01U)
138-
#define MPU_INSTRUCTION_ACCESS_DISABLE ((uint8_t)0x01U)
139-
#define MPU_PRIVILEGED_DEFAULT ((uint32_t)0x00000004U)
140-
141-
// Disable the MPU
142-
__DMB();
143-
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
144-
MPU->CTRL = 0;
145-
146-
// Configure the region
147-
MPU->RNR = MPU_REGION_NUMBER0;
148-
MPU->RBAR = 0xC0000000;
149-
MPU->RASR = (MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos) | (MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos) |
150-
(MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos) | (MPU_ACCESS_NOT_SHAREABLE << MPU_RASR_S_Pos) |
151-
(MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos) | (MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos) |
152-
(0x00 << MPU_RASR_SRD_Pos) | (MPU_REGION_SIZE_8MB << MPU_RASR_SIZE_Pos) |
153-
(MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos);
154-
155-
// Enable the MPU
156-
MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk;
157-
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
158-
__DSB();
159-
__ISB();
124+
MPU_Region_InitTypeDef MPU_InitStruct;
125+
126+
// Configure the MPU attributes for SDRAM
127+
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
128+
MPU_InitStruct.BaseAddress = 0xD0000000;
129+
MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
130+
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
131+
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
132+
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
133+
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
134+
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
135+
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
136+
MPU_InitStruct.SubRegionDisable = 0x00;
137+
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
138+
139+
HAL_MPU_ConfigRegion(&MPU_InitStruct);
160140
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// See LICENSE file in the project root for full license information.
4+
//
5+
6+
#include <ch.h>
7+
#include <hal.h>
8+
#include <stm32_registry.h>
9+
#include <hal_nf_community.h>
10+
11+
extern void Target_ExternalMemoryConfigMPU();
12+
13+
void Target_ConfigNonCacheableMemory()
14+
{
15+
// region
16+
MPU->RNR = ((uint32_t)MPU_REGION_1);
17+
18+
// base address
19+
MPU->RBAR = ((uint32_t)0x20000000U);
20+
21+
// size and other configs
22+
MPU->RASR =
23+
((uint32_t)MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE | MPU_RASR_ATTR_S | MPU_RASR_SIZE_128K |
24+
MPU_RASR_ENABLE);
25+
}
26+
27+
void Target_ConfigMPU()
28+
{
29+
// disable MPU
30+
HAL_MPU_Disable();
31+
32+
// config MPU for external memory
33+
Target_ExternalMemoryConfigMPU();
34+
35+
// config MPU for non cacheable memory
36+
Target_ConfigNonCacheableMemory();
37+
38+
// enable MPU
39+
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
40+
}

0 commit comments

Comments
 (0)