Skip to content

Commit d108a9a

Browse files
authored
Hard fault caused by unaligned Memory Access on STM32F769 series (#2820)
***NO_CI***
1 parent c174a25 commit d108a9a

File tree

1 file changed

+63
-5
lines changed

1 file changed

+63
-5
lines changed

targets/ChibiOS/ST_STM32F769I_DISCOVERY/target_external_memory.c

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

72+
void SetupDeviceMemoryToEliminateUnalignedAccess();
73+
7274
// SDRAM driver configuration structure.
7375
static const SDRAMConfig sdram_cfg = {
7476
.sdcr = (uint32_t)FMC_ColumnBits_Number_8b | FMC_RowBits_Number_12b | FMC_SDMemory_Width_32b |
@@ -92,11 +94,67 @@ static const SDRAMConfig sdram_cfg = {
9294

9395
void Target_ExternalMemoryInit()
9496
{
97+
SetupDeviceMemoryToEliminateUnalignedAccess();
9598
fsmcSdramInit();
96-
97-
// FIXME
98-
// this swaps SDRAM address to 0x60000000 and makes it L1 cacheable
99-
// SYSCFG->MEMRMP |= SYSCFG_MEMRMP_SWP_FMC_0;
100-
10199
fsmcSdramStart(&SDRAMD, &sdram_cfg);
102100
}
101+
102+
void SetupDeviceMemoryToEliminateUnalignedAccess()
103+
{
104+
// ARM: STM32F7: hard fault caused by unaligned Memory Access
105+
// reference https://www.keil.com/support/docs/3777%20%20.htm
106+
// SYMPTOM
107+
// If you use an STM32F7xx microcontroller with an external SDRAM,
108+
// the Cortex-M7 core may unexpectedly run into the hard fault handler because of unaligned access.
109+
// This may happen for example, when the frame buffer of an LCD, a RAM filesystem or any other data is
110+
// located into the SDRAM address range 0xC0000000 - 0xC03FFFFF (max. 4MB).
111+
// The hard fault is executed although the bit UNALIGN_TRP (bit 3) in the CCR register is not enabled.
112+
113+
// CAUSE
114+
// In general, RAM accesses on Cortex-M7 based devices do not have to be aligned in any way.
115+
// The Cortex-M7 core can handle unaligned accesses by hardware.
116+
// Usually, variables should be naturally aligned because these accesses are slightly faster than unaligned
117+
// accesses.
118+
119+
// STM32F7xx devices have the external SDRAM mapped to the
120+
// address range 0xC0000000 - 0xC03FFFFF (max. 4MB).
121+
// According to the ARMv7-M Architecture Reference Manual chapter B3.1 (table B3-1),
122+
// the area 0xC0000000-0xDFFFFFFF (32MB) is specified as Device Memory Type.
123+
// According to chapter A3.2.1, all accesses to Device Memory Types must be naturally aligned.
124+
// If they are not, a hard fault will execute no matter if the bit UNALIGN_TRP (bit 3) in the CCR register is
125+
// enabled or not.
126+
127+
// Solution recommended by KEIL
128+
129+
#define MPU_REGION_ENABLE ((uint8_t)0x01U)
130+
#define MPU_REGION_SIZE_4MB ((uint8_t)0x15)
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_4MB << 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();
160+
}

0 commit comments

Comments
 (0)